1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-06-02 Chushicheng the first version
9 */
10 #include "drv_soft_spi.h"
11 #include "board.h"
12
13 #if defined BSP_USING_SOFT_SPI
14 #define LOG_TAG "drv.soft_spi"
15 #include <rtdbg.h>
16
17 static struct pico_soft_spi_config soft_spi_config[] =
18 {
19 #ifdef BSP_USING_SOFT_SPI0
20 SOFT_SPI0_BUS_CONFIG,
21 #endif
22 #ifdef BSP_USING_SOFT_SPI1
23 SOFT_SPI1_BUS_CONFIG,
24 #endif
25 };
26
27 static struct pico_soft_spi spi_obj[sizeof(soft_spi_config) / sizeof(soft_spi_config[0])];
28
29 /**
30 * Attach the spi device to soft SPI bus, this function must be used after initialization.
31 */
rt_hw_softspi_device_attach(const char * bus_name,const char * device_name,rt_base_t cs_pin)32 rt_err_t rt_hw_softspi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
33 {
34 rt_err_t result;
35 struct rt_spi_device *spi_device;
36
37 /* attach the device to soft spi bus*/
38 spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
39 RT_ASSERT(spi_device != RT_NULL);
40
41 result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL);
42 return result;
43 }
44
pico_spi_gpio_init(struct pico_soft_spi * spi)45 static void pico_spi_gpio_init(struct pico_soft_spi *spi)
46 {
47 struct pico_soft_spi_config *cfg = (struct pico_soft_spi_config *)spi->cfg;
48 rt_pin_mode(cfg->sck, PIN_MODE_OUTPUT);
49 rt_pin_mode(cfg->miso, PIN_MODE_INPUT);
50 rt_pin_mode(cfg->mosi, PIN_MODE_OUTPUT);
51
52 rt_pin_write(cfg->miso, PIN_HIGH);
53 rt_pin_write(cfg->sck, PIN_HIGH);
54 rt_pin_write(cfg->mosi, PIN_HIGH);
55 }
56
pico_tog_sclk(void * data)57 static void pico_tog_sclk(void *data)
58 {
59 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
60 if(rt_pin_read(cfg->sck) == PIN_HIGH)
61 {
62 rt_pin_write(cfg->sck, PIN_LOW);
63 }
64 else
65 {
66 rt_pin_write(cfg->sck, PIN_HIGH);
67 }
68 }
69
pico_set_sclk(void * data,rt_int32_t state)70 static void pico_set_sclk(void *data, rt_int32_t state)
71 {
72 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
73 if (state)
74 {
75 rt_pin_write(cfg->sck, PIN_HIGH);
76 }
77 else
78 {
79 rt_pin_write(cfg->sck, PIN_LOW);
80 }
81 }
82
pico_set_mosi(void * data,rt_int32_t state)83 static void pico_set_mosi(void *data, rt_int32_t state)
84 {
85 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
86 if (state)
87 {
88 rt_pin_write(cfg->mosi, PIN_HIGH);
89 }
90 else
91 {
92 rt_pin_write(cfg->mosi, PIN_LOW);
93 }
94 }
95
pico_set_miso(void * data,rt_int32_t state)96 static void pico_set_miso(void *data, rt_int32_t state)
97 {
98 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
99 if (state)
100 {
101 rt_pin_write(cfg->miso, PIN_HIGH);
102 }
103 else
104 {
105 rt_pin_write(cfg->miso, PIN_LOW);
106 }
107 }
108
pico_get_sclk(void * data)109 static rt_int32_t pico_get_sclk(void *data)
110 {
111 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
112 return rt_pin_read(cfg->sck);
113 }
114
pico_get_mosi(void * data)115 static rt_int32_t pico_get_mosi(void *data)
116 {
117 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
118 return rt_pin_read(cfg->mosi);
119 }
120
pico_get_miso(void * data)121 static rt_int32_t pico_get_miso(void *data)
122 {
123 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
124 return rt_pin_read(cfg->miso);
125 }
126
pico_dir_mosi(void * data,rt_int32_t state)127 static void pico_dir_mosi(void *data, rt_int32_t state)
128 {
129 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
130 if (state)
131 {
132 rt_pin_mode(cfg->mosi, PIN_MODE_INPUT);
133 }
134 else
135 {
136 rt_pin_mode(cfg->mosi, PIN_MODE_OUTPUT);
137 }
138 }
139
pico_dir_miso(void * data,rt_int32_t state)140 static void pico_dir_miso(void *data, rt_int32_t state)
141 {
142 struct pico_soft_spi_config* cfg = (struct pico_soft_spi_config*)data;
143 if (state)
144 {
145 rt_pin_mode(cfg->miso, PIN_MODE_INPUT);
146 }
147 else
148 {
149 rt_pin_mode(cfg->miso, PIN_MODE_OUTPUT);
150 }
151 }
152
pico_udelay(rt_uint32_t us)153 static void pico_udelay(rt_uint32_t us)
154 {
155 busy_wait_us_32(us);
156 }
157
pico_pin_init(void)158 static void pico_pin_init(void)
159 {
160 rt_size_t obj_num = sizeof(spi_obj) / sizeof(struct pico_soft_spi);
161
162 for(rt_size_t i = 0; i < obj_num; i++)
163 {
164 pico_spi_gpio_init(&spi_obj[i]);
165 }
166 }
167
168 static struct rt_spi_bit_ops pico_soft_spi_ops =
169 {
170 .data = RT_NULL,
171 .pin_init = pico_pin_init,
172 .tog_sclk = pico_tog_sclk,
173 .set_sclk = pico_set_sclk,
174 .set_mosi = pico_set_mosi,
175 .set_miso = pico_set_miso,
176 .get_sclk = pico_get_sclk,
177 .get_mosi = pico_get_mosi,
178 .get_miso = pico_get_miso,
179 .dir_mosi = pico_dir_mosi,
180 .dir_miso = pico_dir_miso,
181 .udelay = pico_udelay,
182 .delay_us = 1,
183 };
184
185 /* Soft SPI initialization function */
rt_hw_softspi_init(void)186 int rt_hw_softspi_init(void)
187 {
188 rt_size_t obj_num = sizeof(spi_obj) / sizeof(struct pico_soft_spi);
189 rt_err_t result;
190
191 for (rt_size_t i = 0; i < obj_num; i++)
192 {
193 pico_soft_spi_ops.data = (void *)&soft_spi_config[i];
194 spi_obj[i].spi.ops = &pico_soft_spi_ops;
195 spi_obj[i].cfg = (void *)&soft_spi_config[i];
196
197 result = rt_spi_bit_add_bus(&spi_obj[i].spi, soft_spi_config[i].bus_name, &pico_soft_spi_ops);
198 RT_ASSERT(result == RT_EOK);
199 }
200
201 return RT_EOK;
202 }
203 INIT_DEVICE_EXPORT(rt_hw_softspi_init);
204
205 #endif /* BSP_USING_SOFT_SPI */
206