فهرست منبع

[components][drivers]:fix spi bug and add software spi (#9944)

* fix:spi bus issue

* [components][drivers]add software SPI bus support
CYFS 3 ماه پیش
والد
کامیت
599cefe834

+ 177 - 0
components/drivers/spi/Kconfig

@@ -14,6 +14,183 @@ config RT_USING_SPI
                 default n
         endif
 
+        menuconfig RT_USING_SOFT_SPI
+            bool "Use GPIO to soft simulate SPI"
+            default n
+            select RT_USING_PIN
+            select RT_USING_SPI_BITOPS
+            if RT_USING_SOFT_SPI
+                menuconfig RT_USING_SOFT_SPI0
+                    bool "Enable SPI0 Bus (software simulation)"
+                    default y
+                    if RT_USING_SOFT_SPI0
+                        config RT_SOFT_SPI0_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 1
+                        config RT_SOFT_SPI0_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 2
+                        config RT_SOFT_SPI0_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 3
+                        config RT_SOFT_SPI0_BUS_NAME
+                            string "Bus name"
+                            default "spi0"
+                        config RT_SOFT_SPI0_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+                menuconfig RT_USING_SOFT_SPI1
+                    bool "Enable SPI1 Bus (software simulation)"
+                    default y
+                    if RT_USING_SOFT_SPI1
+                        config RT_SOFT_SPI1_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 4
+                        config RT_SOFT_SPI1_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 5
+                        config RT_SOFT_SPI1_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 6
+                        config RT_SOFT_SPI1_BUS_NAME
+                            string "Bus name"
+                            default "spi1"
+                        config RT_SOFT_SPI1_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+                menuconfig RT_USING_SOFT_SPI2
+                    bool "Enable SPI2 Bus (software simulation)"
+                    default n
+                    if RT_USING_SOFT_SPI2
+                        config RT_SOFT_SPI2_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 7
+                        config RT_SOFT_SPI2_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 8
+                        config RT_SOFT_SPI2_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 9
+                        config RT_SOFT_SPI2_BUS_NAME
+                            string "Bus name"
+                            default "spi2"
+                        config RT_SOFT_SPI2_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+                menuconfig RT_USING_SOFT_SPI3
+                    bool "Enable SPI3 Bus (software simulation)"
+                    default n
+                    if RT_USING_SOFT_SPI3
+                        config RT_SOFT_SPI3_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 10
+                        config RT_SOFT_SPI3_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 11
+                        config RT_SOFT_SPI3_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 12
+                        config RT_SOFT_SPI3_BUS_NAME
+                            string "Bus name"
+                            default "spi3"
+                        config RT_SOFT_SPI3_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+                menuconfig RT_USING_SOFT_SPI4
+                    bool "Enable SPI4 Bus (software simulation)"
+                    default n
+                    if RT_USING_SOFT_SPI4
+                        config RT_SOFT_SPI4_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 13
+                        config RT_SOFT_SPI4_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 14
+                        config RT_SOFT_SPI4_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 15
+                        config RT_SOFT_SPI4_BUS_NAME
+                            string "Bus name"
+                            default "spi4"
+                        config RT_SOFT_SPI4_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+                menuconfig RT_USING_SOFT_SPI5
+                    bool "Enable SPI5 Bus (software simulation)"
+                    default n
+                    if RT_USING_SOFT_SPI5
+                        config RT_SOFT_SPI5_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 16
+                        config RT_SOFT_SPI5_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 17
+                        config RT_SOFT_SPI5_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 18
+                        config RT_SOFT_SPI5_BUS_NAME
+                            string "Bus name"
+                            default "spi5"
+                        config RT_SOFT_SPI5_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+                menuconfig RT_USING_SOFT_SPI6
+                    bool "Enable SPI6 Bus (software simulation)"
+                    default n
+                    if RT_USING_SOFT_SPI6
+                        config RT_SOFT_SPI6_SCK_PIN
+                            int "SCK pin number"
+                            range 0 32767
+                            default 19
+                        config RT_SOFT_SPI6_MISO_PIN
+                            int "MISO pin number"
+                            range 0 32767
+                            default 20
+                        config RT_SOFT_SPI6_MOSI_PIN
+                            int "MOSI pin number"
+                            range 0 32767
+                            default 21
+                        config RT_SOFT_SPI6_BUS_NAME
+                            string "Bus name"
+                            default "spi6"
+                        config RT_SOFT_SPI6_TIMING_DELAY
+                            int "Timing delay (us)"
+                            range 0 32767
+                            default 1
+                    endif
+
+            endif
+
         config RT_USING_QSPI
             bool "Enable QSPI mode"
             default n

+ 3 - 0
components/drivers/spi/SConscript

@@ -10,6 +10,9 @@ LOCAL_CFLAGS = ''
 if GetDepend('RT_USING_SPI_BITOPS'):
     src += ['dev_spi_bit_ops.c']
 
+if GetDepend('RT_USING_SOFT_SPI'):
+    src += ['dev_soft_spi.c']
+
 if GetDepend('RT_USING_QSPI'):
     src += ['dev_qspi_core.c']
 

+ 269 - 0
components/drivers/spi/dev_soft_spi.c

@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2006-2025 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2025-01-23     CYFS          first version
+ */
+#include <rthw.h>
+#include <rtdevice.h>
+#include <dev_spi_bit_ops.h>
+
+#ifdef RT_USING_SOFT_SPI
+#if !defined(RT_USING_SOFT_SPI0) &&\
+    !defined(RT_USING_SOFT_SPI1) && !defined(RT_USING_SOFT_SPI2) &&\
+    !defined(RT_USING_SOFT_SPI3) && !defined(RT_USING_SOFT_SPI4) &&\
+    !defined(RT_USING_SOFT_SPI5) && !defined(RT_USING_SOFT_SPI6)
+    #error "Please define at least one RT_USING_SOFT_SPIx"
+    /*
+    This driver can be disabled at:
+    menuconfig -> RT-Thread Components -> Device Drivers -> Using I2C device drivers
+    */
+#endif
+
+#define DBG_ENABLE
+#define DBG_TAG                         "SPI_S"
+#ifdef RT_SPI_BITOPS_DEBUG
+    #define DBG_LEVEL                   DBG_LOG
+#endif
+#include <rtdbg.h>
+
+/* spi config class */
+struct rt_soft_spi_config
+{
+    rt_base_t       sck;
+    rt_base_t       miso;
+    rt_base_t       mosi;
+    rt_uint32_t     timing_delay;
+    const char      *bus_name;
+};
+
+/* spi dirver class */
+struct rt_soft_spi
+{
+    struct rt_spi_bit_obj spi;
+    struct rt_spi_bit_ops ops;
+    struct rt_soft_spi_config *cfg;
+};
+
+static struct rt_soft_spi_config soft_spi_config[] =
+{
+#ifdef RT_USING_SOFT_SPI0
+    {
+        .sck = RT_SOFT_SPI0_SCK_PIN,
+        .miso = RT_SOFT_SPI0_MISO_PIN,
+        .mosi = RT_SOFT_SPI0_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI0_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI0_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI0*/
+#ifdef RT_USING_SOFT_SPI1
+    {
+        .sck = RT_SOFT_SPI1_SCK_PIN,
+        .miso = RT_SOFT_SPI1_MISO_PIN,
+        .mosi = RT_SOFT_SPI1_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI1_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI1_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI1*/
+#ifdef RT_USING_SOFT_SPI2
+    {
+        .sck = RT_SOFT_SPI2_SCK_PIN,
+        .miso = RT_SOFT_SPI2_MISO_PIN,
+        .mosi = RT_SOFT_SPI2_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI2_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI2_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI2*/
+#ifdef RT_USING_SOFT_SPI3
+    {
+        .sck = RT_SOFT_SPI3_SCK_PIN,
+        .miso = RT_SOFT_SPI3_MISO_PIN,
+        .mosi = RT_SOFT_SPI3_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI3_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI3_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI3*/
+#ifdef RT_USING_SOFT_SPI4
+    {
+        .sck = RT_SOFT_SPI4_SCK_PIN,
+        .miso = RT_SOFT_SPI4_MISO_PIN,
+        .mosi = RT_SOFT_SPI4_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI4_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI4_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI4*/
+#ifdef RT_USING_SOFT_SPI5
+    {
+        .sck = RT_SOFT_SPI5_SCK_PIN,
+        .miso = RT_SOFT_SPI5_MISO_PIN,
+        .mosi = RT_SOFT_SPI5_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI5_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI5_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI5*/
+#ifdef RT_USING_SOFT_SPI6
+    {
+        .sck = RT_SOFT_SPI6_SCK_PIN,
+        .miso = RT_SOFT_SPI6_MISO_PIN,
+        .mosi = RT_SOFT_SPI6_MOSI_PIN,
+        .timing_delay = RT_SOFT_SPI6_TIMING_DELAY,
+        .bus_name = RT_SOFT_SPI6_BUS_NAME,
+    },
+#endif  /*RT_USING_SOFT_SPI6*/
+
+};
+
+static struct rt_soft_spi spi_obj[sizeof(soft_spi_config) / sizeof(soft_spi_config[0])];
+
+static void spi_soft_pin_init(struct rt_soft_spi * soft_spi)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)soft_spi->cfg;
+    rt_pin_mode(cfg->sck, PIN_MODE_OUTPUT);
+    rt_pin_mode(cfg->miso, PIN_MODE_INPUT);
+    rt_pin_mode(cfg->mosi, PIN_MODE_OUTPUT);
+
+    rt_pin_write(cfg->miso, PIN_HIGH);
+    rt_pin_write(cfg->sck, PIN_HIGH);
+    rt_pin_write(cfg->mosi, PIN_HIGH);
+}
+
+
+static void spi_soft_tog_sclk(void *data)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    if(rt_pin_read(cfg->sck) == PIN_HIGH)
+    {
+        rt_pin_write(cfg->sck, PIN_LOW);
+    }
+    else
+    {
+        rt_pin_write(cfg->sck, PIN_HIGH);
+    }
+}
+
+static void spi_soft_set_sclk(void *data, rt_int32_t state)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    if (state)
+    {
+        rt_pin_write(cfg->sck, PIN_HIGH);
+    }
+    else
+    {
+        rt_pin_write(cfg->sck, PIN_LOW);
+    }
+}
+
+static void spi_soft_set_mosi(void *data, rt_int32_t state)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    if (state)
+    {
+        rt_pin_write(cfg->mosi, PIN_HIGH);
+    }
+    else
+    {
+        rt_pin_write(cfg->mosi, PIN_LOW);
+    }
+}
+
+static void spi_soft_set_miso(void *data, rt_int32_t state)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    if (state)
+    {
+        rt_pin_write(cfg->miso, PIN_HIGH);
+    }
+    else
+    {
+        rt_pin_write(cfg->miso, PIN_LOW);
+    }
+}
+
+static rt_int32_t spi_soft_get_sclk(void *data)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    return rt_pin_read(cfg->sck);
+}
+
+static rt_int32_t spi_soft_get_mosi(void *data)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    return rt_pin_read(cfg->mosi);
+}
+
+static rt_int32_t spi_soft_get_miso(void *data)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    return rt_pin_read(cfg->miso);
+}
+
+static void spi_soft_dir_mosi(void *data, rt_int32_t state)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    if (state)
+    {
+        rt_pin_mode(cfg->mosi, PIN_MODE_INPUT);
+    }
+    else
+    {
+        rt_pin_mode(cfg->mosi, PIN_MODE_OUTPUT);
+    }
+}
+
+static void spi_soft_dir_miso(void *data, rt_int32_t state)
+{
+    struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
+    if (state)
+    {
+        rt_pin_mode(cfg->miso, PIN_MODE_INPUT);
+    }
+    else
+    {
+        rt_pin_mode(cfg->miso, PIN_MODE_OUTPUT);
+    }
+}
+
+static struct rt_spi_bit_ops soft_spi_ops=
+{
+    .data = RT_NULL,
+    .pin_init = RT_NULL,
+    .tog_sclk = spi_soft_tog_sclk,
+    .set_sclk = spi_soft_set_sclk,
+    .set_mosi = spi_soft_set_mosi,
+    .set_miso = spi_soft_set_miso,
+    .get_sclk = spi_soft_get_sclk,
+    .get_mosi = spi_soft_get_mosi,
+    .get_miso = spi_soft_get_miso,
+    .dir_mosi = spi_soft_dir_mosi,
+    .dir_miso = spi_soft_dir_miso,
+    .udelay   = rt_hw_us_delay,
+};
+
+/* Soft SPI initialization function */
+int rt_soft_spi_init(void)
+{
+    rt_size_t obj_num = sizeof(spi_obj) / sizeof(struct rt_soft_spi);
+    rt_err_t result;
+
+    for (rt_size_t i = 0; i < obj_num; i++)
+    {
+        rt_memcpy(&spi_obj[i].ops, &soft_spi_ops, sizeof(struct rt_spi_bit_ops));
+        spi_obj[i].ops.data = (void *)&soft_spi_config[i];
+        spi_obj[i].spi.ops = &soft_spi_ops;
+        spi_obj[i].cfg = (void *)&soft_spi_config[i];
+        spi_soft_pin_init(&spi_obj[i]);
+        spi_obj[i].spi.ops->delay_us = soft_spi_config[i].timing_delay;
+        result = rt_spi_bit_add_bus(&spi_obj[i].spi, soft_spi_config[i].bus_name, &spi_obj[i].ops);
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return RT_EOK;
+}
+INIT_PREV_EXPORT(rt_soft_spi_init);
+
+#endif /* RT_USING_SOFT_SPI */
+

+ 75 - 22
components/drivers/spi/dev_spi_bit_ops.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2024, RT-Thread Development Team
+ * Copyright (c) 2006-2025 RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -87,11 +87,23 @@ rt_inline rt_ssize_t spi_xfer_4line_data8(struct rt_spi_bit_ops       *ops,
 
                 TOG_SCLK(ops);
 
-                if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x01; }
-                else                           { rx_data >>= 1; bit = 0x80; }
+                if (config->mode & RT_SPI_MSB)
+                {
+                    rx_data <<= 1; bit = 0x01;
+                }
+                else
+                {
+                    rx_data >>= 1; bit = 0x80;
+                }
 
-                if (GET_MISO(ops)) { rx_data |=  bit; }
-                else               { rx_data &= ~bit; }
+                if (GET_MISO(ops))
+                {
+                    rx_data |=  bit;
+                }
+                else
+                {
+                    rx_data &= ~bit;
+                }
 
                 spi_delay2(ops);
 
@@ -150,11 +162,23 @@ rt_inline rt_ssize_t spi_xfer_4line_data16(struct rt_spi_bit_ops       *ops,
 
                 TOG_SCLK(ops);
 
-                if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x0001; }
-                else                           { rx_data >>= 1; bit = 0x8000; }
+                if (config->mode & RT_SPI_MSB)
+                {
+                    rx_data <<= 1; bit = 0x0001;
+                }
+                else
+                {
+                    rx_data >>= 1; bit = 0x8000;
+                }
 
-                if (GET_MISO(ops)) { rx_data |=  bit; }
-                else               { rx_data &= ~bit; }
+                if (GET_MISO(ops))
+                {
+                    rx_data |=  bit;
+                }
+                else
+                {
+                    rx_data &= ~bit;
+                }
 
                 spi_delay2(ops);
 
@@ -244,11 +268,23 @@ rt_inline rt_ssize_t spi_xfer_3line_data8(struct rt_spi_bit_ops       *ops,
 
                     TOG_SCLK(ops);
 
-                    if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x01; }
-                    else                           { rx_data >>= 1; bit = 0x80; }
+                    if (config->mode & RT_SPI_MSB)
+                    {
+                        rx_data <<= 1; bit = 0x01;
+                    }
+                    else
+                    {
+                        rx_data >>= 1; bit = 0x80;
+                    }
 
-                    if (GET_MOSI(ops)) { rx_data |=  bit; }
-                    else               { rx_data &= ~bit; }
+                    if (GET_MOSI(ops))
+                    {
+                        rx_data |=  bit;
+                    }
+                    else
+                    {
+                        rx_data &= ~bit;
+                    }
 
                     spi_delay2(ops);
 
@@ -345,11 +381,23 @@ rt_inline rt_ssize_t spi_xfer_3line_data16(struct rt_spi_bit_ops       *ops,
 
                     TOG_SCLK(ops);
 
-                    if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x0001; }
-                    else                           { rx_data >>= 1; bit = 0x8000; }
+                    if (config->mode & RT_SPI_MSB)
+                    {
+                        rx_data <<= 1; bit = 0x0001;
+                    }
+                    else
+                    {
+                        rx_data >>= 1; bit = 0x8000;
+                    }
 
-                    if (GET_MOSI(ops)) { rx_data |=  bit; }
-                    else               { rx_data &= ~bit; }
+                    if (GET_MOSI(ops))
+                    {
+                        rx_data |=  bit;
+                    }
+                    else
+                    {
+                        rx_data &= ~bit;
+                    }
 
                     spi_delay2(ops);
 
@@ -456,15 +504,14 @@ rt_ssize_t spi_bit_xfer(struct rt_spi_device *device, struct rt_spi_message *mes
             rt_pin_write(cs_pin, PIN_LOW);
         }
         spi_delay(ops);
+    }
 
         /* spi phase */
-        if (config->mode & RT_SPI_CPHA)
+        if ((config->mode & RT_SPI_CPHA))
         {
             spi_delay(ops);
             TOG_SCLK(ops);
         }
-    }
-
     if (config->mode & RT_SPI_3WIRE)
     {
         if (config->data_width <= 8)
@@ -487,10 +534,15 @@ rt_ssize_t spi_bit_xfer(struct rt_spi_device *device, struct rt_spi_message *mes
             length = spi_xfer_4line_data16(ops, config, message->send_buf, message->recv_buf, message->length);
         }
     }
-
     /* release CS */
-    if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS) && (cs_pin != PIN_NONE))
+    if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS) && (cs_pin != PIN_NONE))
     {
+
+        if ((config->mode & RT_SPI_CPOL) && !GET_SCLK(ops))
+        {
+            spi_delay(ops);
+            TOG_SCLK(ops);
+        }
         spi_delay(ops);
         if (device->config.mode & RT_SPI_CS_HIGH)
         {
@@ -501,6 +553,7 @@ rt_ssize_t spi_bit_xfer(struct rt_spi_device *device, struct rt_spi_message *mes
             rt_pin_write(cs_pin, PIN_HIGH);
         }
         LOG_I("spi release cs\n");
+
     }
 
     return length;

+ 2 - 2
components/drivers/spi/dev_spi_core.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2025 RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -140,7 +140,7 @@ rt_err_t rt_spi_bus_configure(struct rt_spi_device *device)
         result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
         if (result == RT_EOK)
         {
-            if (device->bus->owner == device)
+            if (device->bus->owner == RT_NULL || device->bus->owner == device)
             {
                 /* current device is using, re-configure SPI bus */
                 result = device->bus->ops->configure(device, &device->config);