Browse Source

[bsp][ch32v307v]添加了硬件iic驱动

白熊 1 year ago
parent
commit
f3d7c8567a

+ 3 - 0
bsp/wch/risc-v/Libraries/ch32_drivers/SConscript

@@ -18,6 +18,9 @@ if  GetDepend('SOC_RISCV_FAMILY_CH32'):
     if GetDepend('BSP_USING_DAC'):
         src += ['drv_dac.c']
 
+    if GetDepend('BSP_USING_I2C'):
+        src += ['drv_i2c.c']
+
     if GetDepend('BSP_USING_SOFT_I2C'):
         src += ['drv_soft_i2c.c']
 

+ 252 - 0
bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.c

@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-4-1       IceBear003   the first version
+ */
+
+#include "board.h"
+#include "drv_i2c.h"
+
+#ifdef BSP_USING_HWI2C
+
+#define LOG_TAG "drv.hwi2c"
+#include "drv_log.h"
+
+#if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2)
+#error "Please define at least one BSP_USING_I2Cx"
+/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
+#endif
+
+#define TIMEOUT 0xFF
+
+#ifdef BSP_USING_I2C1
+struct i2c_bus_device i2c_bus1;
+#endif
+#ifdef BSP_USING_I2C2
+struct i2c_bus_device i2c_bus2;
+#endif
+
+static int i2c_read(I2C_TypeDef *i2c_periph,
+                         rt_uint16_t addr,
+                         rt_uint8_t flags,
+                         rt_uint16_t len,
+                         rt_uint8_t *buf)
+{
+    rt_uint16_t try = 0;
+    while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY))
+        if (try++ >= TIMEOUT) return -1;
+
+    I2C_GenerateSTART(i2c_periph, ENABLE);
+
+    try = 0;
+    while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))                       //EVT5
+        if (try++ >= TIMEOUT) return -1;
+
+    if(flags & RT_I2C_ADDR_10BIT)   //10-bit address mode
+    {
+        rt_uint8_t frame_head = 0xF0 + (addr >> 8) << 1;                                    //11110XX0
+        I2C_SendData(i2c_periph, frame_head);                                               //FrameHead
+
+        try = 0;
+        while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10))                //EVT9
+            if (try++ >= TIMEOUT) return -1;
+
+        I2C_SendData(i2c_periph,0xff & addr);
+
+        try = 0;
+        while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))     //EVT6
+            if (try++ >= TIMEOUT) return -1;
+
+        I2C_GenerateSTART(i2c_periph, ENABLE);                                              //Sr
+
+        try = 0;
+        while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))                   //EVT5
+            if (try++ >= TIMEOUT) return -1;
+
+        I2C_SendData(i2c_periph,frame_head);                                                //Resend FrameHead
+    }
+    else
+    {
+        I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Receiver);
+    }
+
+    try = 0;
+    while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))            //EVT6
+        if (try++ >= TIMEOUT) return -1;
+
+    while(len-- > 0)
+    {
+
+        try = 0;
+        while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_RXNE))                               //Got ACK For the Last Byte
+            if (try++ >= TIMEOUT) return -1;
+
+        *(buf++)=I2C_ReceiveData(i2c_periph);
+    }
+
+    I2C_GenerateSTOP(i2c_periph, ENABLE);
+}
+
+static int i2c_write(I2C_TypeDef *i2c_periph,
+                            rt_uint16_t addr,
+                            rt_uint8_t flags,
+                            rt_uint8_t *buf,
+                            rt_uint16_t len)
+{
+    rt_uint16_t try = 0;
+    while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY))
+        if (try++ >= TIMEOUT) return -1;
+
+    I2C_GenerateSTART(i2c_periph, ENABLE);
+
+    try = 0;
+    while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))                       //EVT5
+        if (try++ >= TIMEOUT) return -1;
+
+    if(flags & RT_I2C_ADDR_10BIT)   //10-bit address mode
+    {
+        I2C_SendData(i2c_periph,0xF0 + (addr >> 8) << 1);                                   //FrameHead 11110XX0
+
+        try = 0;
+        while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10))                //EVT9
+            if (try++ >= TIMEOUT) return -1;
+
+        I2C_SendData(i2c_periph,0xff & addr);
+    }
+    else    //7-bit address mode
+    {
+        I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Transmitter);
+    }
+
+    try = 0;
+    while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))         //EVT6
+        if (try++ >= TIMEOUT) return -1;
+
+    //Missing Evt8_1 (No definition)
+
+    while(len-- > 0)
+    {
+        try = 0;
+        while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_TXE))                                //Got ACK For the Last Byte
+            if (try++ >= TIMEOUT) return -1;
+
+        I2C_SendData(i2c_periph,*(buf++));
+    }
+
+    try = 0;
+    while(!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_BYTE_TRANSMITTING))                  //Last byte sent successfully
+        if (try++ >= TIMEOUT) return -1;
+
+    I2C_GenerateSTOP(i2c_periph, ENABLE);
+}
+
+rt_size_t i2c_master_xfer(struct rt_i2c_bus_device *bus,
+                            struct rt_i2c_msg msgs[],
+                                    rt_uint32_t num)
+{
+    struct rt_i2c_msg *msg;
+    struct i2c_bus_device *i2c_bus_dev;
+    rt_uint32_t index;
+
+    i2c_bus_dev = (struct i2c_bus_device *)bus;
+
+    for (index = 0; index < num; index++)
+    {
+        msg = &msgs[index];
+        if (msg->flags & RT_I2C_RD)
+        {
+            i2c_read(i2c_bus_dev->periph,
+                          msg->addr,
+                          msg->flags,
+                          msg->len,
+                          msg->buf);
+        }
+        else
+        {
+            i2c_write(i2c_bus_dev->periph,
+                           msg->addr,
+                           msg->flags,
+                           msg->buf,
+                           msg->len);
+        }
+    }
+
+    return index;
+}
+
+static const struct rt_i2c_bus_device_ops ch32_i2c_ops =
+{
+        .master_xfer = i2c_master_xfer,
+        .slave_xfer = RT_NULL,                   //Not Used in i2c_core?
+        .i2c_bus_control = RT_NULL
+};
+
+int rt_hw_i2c_init(struct i2c_config *config = &{5000, I2C_DutyCycle_2, 0, I2C_Ack_Disable, I2C_AcknowledgedAddress_7bit})
+{
+    int result = RT_EOK;
+
+    GPIO_InitTypeDef GPIO_InitStructure = {0};
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
+
+    I2C_InitTypeDef I2C_InitTSturcture = {0};
+    I2C_StructInit(&I2C_InitTSturcture);
+    I2C_InitTSturcture.I2C_ClockSpeed = config->clock_speed;
+    I2C_InitTSturcture.I2C_DutyCycle = config->duty_cycle;
+    I2C_InitTSturcture.I2C_OwnAddress1 = config->own_address;
+    I2C_InitTSturcture.I2C_Ack = config->enable_ack ? I2C_Ack_Enable : I2C_Ack_Disable;
+    I2C_InitTSturcture.I2C_AcknowledgedAddress = config->is_7_bit_address ? I2C_AcknowledgedAddress_7bit : I2C_AcknowledgedAddress_10bit;
+
+
+#ifdef BSP_USING_I2C1
+
+    i2c_bus1.periph = I2C1;
+
+    //Clock & IO Initialization
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
+
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
+
+    //I2C Initialization Config
+    I2C_Init(I2C1, &I2C_InitTSturcture);
+    I2C_Cmd(I2C1, ENABLE);
+
+    //Hook to RT-Thread
+    i2c_bus1.parent.ops = &ch32_i2c_ops;
+    result += rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1");
+
+#endif
+
+#ifdef BSP_USING_I2C2
+
+    i2c_bus2.periph = I2C2;
+
+    //Clock & IO Initialization
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
+
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    //I2C Initialization Config
+    I2C_Init(I2C2, &I2C_InitTSturcture);
+    I2C_Cmd(I2C2, ENABLE);
+
+    //Hook to RT-Thread
+    i2c_bus2.parent.ops = &ch32_i2c_ops;
+    result += rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2");
+
+#endif
+
+    return result;
+}
+
+#endif //BSP_USING_HWI2C

+ 36 - 0
bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-4-1       IceBear003   the first version
+ */
+
+#ifndef __DRV_I2C_H_
+#define __DRV_I2C_H_
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+struct i2c_bus_device
+{
+    struct rt_i2c_bus_device parent;
+    I2C_TypeDef *periph;
+};
+
+struct i2c_config
+{
+    rt_uint32_t clock_speed;
+    uint16_t duty_cycle;
+    uint16_t own_address;
+    uint8_t enable_ack;
+    uint8_t is_7_bit_address;
+};
+
+struct i2c_config i2c_default_conf={5000, I2C_Mode_I2C, I2C_DutyCycle_2, 0, I2C_Ack_Disable, I2C_AcknowledgedAddress_7bit};
+
+int rt_hw_i2c_init(struct i2c_config *config);
+
+#endif

+ 15 - 0
bsp/wch/risc-v/ch32v307v-r1/board/Kconfig

@@ -121,6 +121,21 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_I2C
+        bool "Enable I2C"
+        select RT_USING_I2C
+
+        if BSP_USING_I2C
+            config BSP_USING_I2C1
+                bool "Enable I2C1"
+                default n
+
+            config BSP_USING_I2C2
+                bool "Enable I2C2"
+                default n
+
+        endif
+
     menuconfig BSP_USING_SOFT_I2C
         bool "Enable I2C Bus"
         select RT_USING_I2C