浏览代码

AVR32: Software I2C driver: Initial working commit (#8324)

implemented the software I2C drivers for the AVR32 target.
Raman 1 年之前
父节点
当前提交
fe11e85eea

+ 9 - 15
bsp/avr32/at32uc3a0256/.config

@@ -8,6 +8,7 @@
 #
 CONFIG_RT_NAME_MAX=8
 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set
+# CONFIG_RT_USING_NANO is not set
 # CONFIG_RT_USING_AMP is not set
 # CONFIG_RT_USING_SMP is not set
 CONFIG_RT_CPUS_NR=1
@@ -34,10 +35,7 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=512
 # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
 # CONFIG_RT_USING_TINY_FFS is not set
 # CONFIG_RT_KPRINTF_USING_LONGLONG is not set
-CONFIG_RT_USING_DEBUG=y
-CONFIG_RT_DEBUGING_COLOR=y
-# CONFIG_RT_DEBUGING_CONTEXT is not set
-# CONFIG_RT_DEBUGING_INIT is not set
+# CONFIG_RT_USING_DEBUG is not set
 
 #
 # Inter-Thread communication
@@ -206,6 +204,12 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
 # CONFIG_RT_USING_LWIP is not set
 # CONFIG_RT_USING_AT is not set
 
+#
+# Memory protection
+#
+# CONFIG_RT_USING_MEM_PROTECTION is not set
+# CONFIG_RT_USING_HW_STACK_GUARD is not set
+
 #
 # Utilities
 #
@@ -218,17 +222,6 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
 # CONFIG_RT_USING_RT_LINK is not set
 # CONFIG_RT_USING_VBUS is not set
 
-#
-# Memory management
-#
-# CONFIG_RT_USING_MEMBLOCK is not set
-
-#
-# Memory protection
-#
-# CONFIG_RT_USING_MEM_PROTECTION is not set
-# CONFIG_RT_USING_HW_STACK_GUARD is not set
-
 #
 # RT-Thread Utestcases
 #
@@ -1014,3 +1007,4 @@ CONFIG_BSP_UART1_RX_PIN_5=y
 # CONFIG_BSP_UART1_RX_PIN_96 is not set
 CONFIG_BSP_UART1_RX_PIN=5
 CONFIG_BSP_UART1_RX_PIN_FUNCTION=0
+# CONFIG_BSP_USING_SOFT_I2C is not set

+ 20 - 0
bsp/avr32/at32uc3a0256/Kconfig

@@ -132,5 +132,25 @@ menu "On-chip Peripheral Drivers"
                     default 1 if BSP_UART1_RX_PIN_96
             endif
         endif
+
+    menuconfig BSP_USING_SOFT_I2C
+        bool "Enable I2C BUS (software simulation)"
+        default n
+        select RT_USING_I2C
+        select RT_USING_I2C_BITOPS
+        select RT_USING_PIN
+        if BSP_USING_SOFT_I2C
+            config BSP_USING_SOFT_I2C1
+                bool "Enable I2C1 Bus (software simulation)"
+                default n
+                if BSP_USING_SOFT_I2C1
+                    config BSP_SOFT_I2C1_SCL_PIN
+                        int "I2C1 SCL pin number (GP)"
+                        default 30
+                    config BSP_SOFT_I2C1_SDA_PIN
+                        int "I2C1 SDA pin number (GP)"
+                        default 29
+                endif
+        endif
 endmenu
 endmenu

+ 6 - 0
bsp/avr32/at32uc3a0256/board.c

@@ -8,6 +8,7 @@
  * 2010-03-30     Kyle            First version
  * 2023-10-13     Raman Gopalan   Move UART specific code sections into the drv_uart files
  * 2023-10-20     Raman Gopalan   Initialize GPIO sub-system
+ * 2023-12-01     Raman Gopalan   Initialize software I2C sub-system
  */
 
 #include <rtthread.h>
@@ -18,6 +19,7 @@
 #include "intc.h"
 #include "drv_uart.h"
 #include "drv_gpio.h"
+#include "drv_soft_i2c.h"
 
 /**
  * System tick interrupt handler.
@@ -78,6 +80,10 @@ void rt_hw_board_init(void)
     rt_hw_gpio_init();
 #endif
 
+#ifdef BSP_USING_SOFT_I2C
+    rt_sw_i2c_init();
+#endif
+
 #ifdef RT_USING_CONSOLE
     rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
 #endif

+ 2 - 7
bsp/avr32/at32uc3a0256/rtconfig.h

@@ -24,8 +24,6 @@
 
 /* kservice optimization */
 
-#define RT_USING_DEBUG
-#define RT_DEBUGING_COLOR
 
 /* Inter-Thread communication */
 
@@ -103,13 +101,10 @@
 /* Network */
 
 
-/* Utilities */
-
-
-/* Memory management */
+/* Memory protection */
 
 
-/* Memory protection */
+/* Utilities */
 
 
 /* RT-Thread Utestcases */

+ 7 - 7
bsp/avr32/drivers/SConscript

@@ -7,16 +7,16 @@ cwd = GetCurrentDir()
 # add the general drivers.
 src = []
 
-if GetDepend(['RT_USING_PIN']):
+if GetDepend(['BSP_USING_PIN']):
     src += ['drv_gpio.c']
 
-if GetDepend(['RT_USING_SERIAL']):
-    if GetDepend(['RT_USING_SERIAL_V2']):
-        src += ['drv_uart_v2.c']
-    else:
-        src += ['drv_uart.c']
+if GetDepend(['BSP_USING_UART']):
+    src += ['drv_uart.c']
 
-path =  [cwd]
+if GetDepend(['BSP_USING_SOFT_I2C']):
+    src += ['drv_soft_i2c.c']
+
+path = [cwd]
 
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
 

+ 168 - 0
bsp/avr32/drivers/drv_soft_i2c.c

@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author           Notes
+ * 2023/12/01     Raman Gopalan    First version
+ */
+#include "drv_soft_i2c.h"
+
+#ifdef BSP_USING_SOFT_I2C
+#define DBG_LEVEL   DBG_LOG
+#include <rtdbg.h>
+#define LOG_TAG "DRV.I2C"
+
+static const struct avr32_soft_i2c_config soft_i2c_config[] =
+{
+#ifdef BSP_USING_SOFT_I2C1
+    I2C1_BUS_CONFIG,
+#endif
+};
+
+static struct avr32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
+
+/**
+ * This function initializes the I2C pin.
+ *
+ * @param AVR32 I2C driver class.
+ */
+static void avr32_i2c_gpio_init(struct avr32_i2c *i2c)
+{
+    struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)i2c->ops.data;
+
+    rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
+    gpio_set_gpio_open_drain_pin(cfg->scl);
+    
+    rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
+    gpio_set_gpio_open_drain_pin(cfg->sda);
+}
+
+/**
+ * This function sets the SDA pin.
+ *
+ * @param AVR32 config class.
+ * @param The SDA pin state.
+ */
+static void avr32_set_sda(void *data, rt_int32_t state)
+{
+    struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
+    if (state)
+    {
+	gpio_set_gpio_open_drain_pin(cfg->sda);
+    }
+    else
+    {
+	gpio_clr_gpio_open_drain_pin(cfg->sda);
+    }
+}
+
+/**
+ * This function sets the SCL pin.
+ *
+ * @param AVR32 config class.
+ * @param The SCL pin state.
+ */
+static void avr32_set_scl(void *data, rt_int32_t state)
+{
+    struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
+    if (state)
+    {
+	gpio_set_gpio_open_drain_pin(cfg->scl);
+    }
+    else
+    {
+	gpio_clr_gpio_open_drain_pin(cfg->scl);
+    }
+}
+
+/**
+ * This function gets the SDA pin state.
+ *
+ * @param The SDA pin state.
+ */
+static rt_int32_t avr32_get_sda(void *data)
+{
+    struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
+    return gpio_get_gpio_open_drain_pin_output_value(cfg->sda);
+}
+
+/**
+ * This function gets the SCL pin state.
+ *
+ * @param The SCL pin state.
+ */
+static rt_int32_t avr32_get_scl(void *data)
+{
+    struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
+    return gpio_get_gpio_open_drain_pin_output_value(cfg->scl);
+}
+
+static const struct rt_i2c_bit_ops avr32_bit_ops_default =
+{
+    .data     = RT_NULL,
+    .set_sda  = avr32_set_sda,
+    .set_scl  = avr32_set_scl,
+    .get_sda  = avr32_get_sda,
+    .get_scl  = avr32_get_scl,
+    .udelay   = rt_hw_us_delay,
+    .delay_us = 1,
+    .timeout  = 100
+};
+
+/**
+ * If I2C is locked, this function will unlock it.
+ *
+ * @param AVR32 config class
+ *
+ * @return RT_EOK indicates successful unlock.
+ */
+static rt_err_t avr32_i2c_bus_unlock(const struct avr32_soft_i2c_config *cfg)
+{
+    rt_int32_t i = 0;
+
+    if (PIN_LOW == gpio_get_gpio_open_drain_pin_output_value(cfg->sda))
+    {
+        while (i++ < 9)
+        {
+	    gpio_set_gpio_open_drain_pin(cfg->scl);
+	    rt_hw_us_delay(100);
+	    gpio_clr_gpio_open_drain_pin(cfg->scl);
+	    rt_hw_us_delay(100);
+        }
+    }
+    if (PIN_LOW == gpio_get_gpio_open_drain_pin_output_value(cfg->sda))
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+/* I2C initialization function */
+int rt_sw_i2c_init(void)
+{
+    rt_err_t result;
+    rt_size_t i;
+
+    for (i = 0; i < sizeof(i2c_obj) / sizeof(struct avr32_i2c); i++)
+    {
+        i2c_obj[i].ops = avr32_bit_ops_default;
+        i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
+        i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
+        avr32_i2c_gpio_init(&i2c_obj[i]);
+        result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
+        RT_ASSERT(result == RT_EOK);
+        avr32_i2c_bus_unlock(&soft_i2c_config[i]);
+
+        LOG_D("Software simulation %s init done, pin SCL: %d, pin SDA %d",
+        soft_i2c_config[i].bus_name,
+        soft_i2c_config[i].scl,
+        soft_i2c_config[i].sda);
+    }
+
+    return RT_EOK;
+}
+
+#endif /* BSP_USING_SOFT_I2C */

+ 46 - 0
bsp/avr32/drivers/drv_soft_i2c.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author           Notes
+ * 2023/12/01     Raman Gopalan    First version
+ */
+
+#ifndef __DRV_SOFT_I2C__
+#define __DRV_SOFT_I2C__
+
+#include <rtdevice.h>
+#include "drv_gpio.h"
+#include "gpio.h"
+
+#ifdef BSP_USING_SOFT_I2C
+/* AVR32 software I2C driver class */
+struct avr32_i2c
+{
+    struct rt_i2c_bit_ops ops;
+    struct rt_i2c_bus_device i2c2_bus;
+};
+
+/* AVR32 config class */
+struct avr32_soft_i2c_config
+{
+    rt_uint8_t scl;
+    rt_uint8_t sda;
+    const char *bus_name;
+};
+
+#ifdef BSP_USING_SOFT_I2C1
+#define I2C1_BUS_CONFIG                                  \
+    {                                                    \
+        .scl = BSP_SOFT_I2C1_SCL_PIN,                    \
+        .sda = BSP_SOFT_I2C1_SDA_PIN,                    \
+        .bus_name = "i2c1",                              \
+    }
+#endif
+
+int rt_sw_i2c_init(void);
+
+#endif /* BSP_USING_SOFT_I2C */
+#endif /* #ifndef __DRV_SOFT_I2C__ */