summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/drivers/spi/Kconfig177
-rw-r--r--components/drivers/spi/SConscript3
-rw-r--r--components/drivers/spi/dev_soft_spi.c269
-rw-r--r--components/drivers/spi/dev_spi_bit_ops.c97
-rw-r--r--components/drivers/spi/dev_spi_core.c4
5 files changed, 526 insertions, 24 deletions
diff --git a/components/drivers/spi/Kconfig b/components/drivers/spi/Kconfig
index 8925d8e9e8..f2fbd7edad 100644
--- a/components/drivers/spi/Kconfig
+++ b/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
diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript
index 6897dab6d3..fc608c46ae 100644
--- a/components/drivers/spi/SConscript
+++ b/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']
diff --git a/components/drivers/spi/dev_soft_spi.c b/components/drivers/spi/dev_soft_spi.c
new file mode 100644
index 0000000000..a308299f6c
--- /dev/null
+++ b/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 */
+
diff --git a/components/drivers/spi/dev_spi_bit_ops.c b/components/drivers/spi/dev_spi_bit_ops.c
index d2a26a766d..4f216a9a3b 100644
--- a/components/drivers/spi/dev_spi_bit_ops.c
+++ b/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;
diff --git a/components/drivers/spi/dev_spi_core.c b/components/drivers/spi/dev_spi_core.c
index d84aaac055..3a3008d6e7 100644
--- a/components/drivers/spi/dev_spi_core.c
+++ b/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);