1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-02-22 airm2m first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "drivers/dev_spi.h"
14 #include "board.h"
15 #include "drv_spi.h"
16
17 #ifdef BSP_USING_SPI
18
19 #define LOG_TAG "drv.spi"
20 #include "drv_log.h"
21
22 #ifndef ITEM_NUM
23 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
24 #endif
25
26 struct spi_bus_device
27 {
28 struct rt_spi_bus parent;
29 char *name;
30 SPI_TypeDef *periph;
31 rt_base_t cs_pin;
32 struct rt_spi_device spi_device;
33 };
34
35 static struct spi_bus_device spi_bus_device_list[] = {
36 #ifdef BSP_USING_SPI1
37 {.periph = SPI1,
38 .name = "spi1"},
39 #endif
40
41 #ifdef BSP_USING_SPI2
42 {.periph = SPI2,
43 .name = "spi2"},
44 #endif
45 };
46
47 /**
48 * Attach the spi device to SPI bus, this function must be used after initialization.
49 */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_uint32_t pin)50 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
51 {
52 rt_err_t result;
53 struct rt_spi_bus *spi_bus;
54 struct spi_bus_device *spi_bus_dev;
55
56 RT_ASSERT(bus_name != RT_NULL);
57 RT_ASSERT(device_name != RT_NULL);
58
59 spi_bus = (struct rt_spi_bus *)rt_device_find(bus_name);
60
61 RT_ASSERT(spi_bus != RT_NULL);
62
63 spi_bus_dev = (struct spi_bus_device *)spi_bus;
64
65 spi_bus_dev->cs_pin = pin;
66
67 //often active low, output from master
68 rt_pin_mode(spi_bus_dev->cs_pin, PIN_MODE_OUTPUT);
69 rt_pin_write(spi_bus_dev->cs_pin, PIN_HIGH);
70
71 result = rt_spi_bus_attach_device(&spi_bus_dev->spi_device, device_name, bus_name, RT_NULL);
72
73 if (result != RT_EOK)
74 {
75 LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
76 }
77
78 LOG_D("%s attach to %s done", device_name, bus_name);
79
80 return result;
81 }
82
air32_spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)83 static rt_err_t air32_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
84 {
85 struct rt_spi_bus *spi_bus;
86 struct spi_bus_device *spi_bus_dev;
87 rt_uint32_t spi_clock;
88
89 SPI_InitTypeDef SPI_InitStruct;
90
91 RT_ASSERT(device != RT_NULL);
92 RT_ASSERT(configuration != RT_NULL);
93
94 //device is not RT_NULL, so spi_bus not need check
95 spi_bus = (struct rt_spi_bus *)device->bus;
96 spi_bus_dev = (struct spi_bus_device *)spi_bus;
97
98 air32_spi_clock_and_io_init(spi_bus_dev->periph);
99
100 spi_clock = air32_spi_clock_get(spi_bus_dev->periph);
101
102 if (configuration->data_width <= 8)
103 {
104 SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
105 }
106 else if (configuration->data_width <= 16)
107 {
108 SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b;
109 }
110 else
111 {
112 return -RT_EIO;
113 }
114
115 if (configuration->max_hz >= spi_clock / 2)
116 {
117 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
118 }
119 else if (configuration->max_hz >= spi_clock / 4)
120 {
121 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
122 }
123 else if (configuration->max_hz >= spi_clock / 8)
124 {
125 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
126 }
127 else if (configuration->max_hz >= spi_clock / 16)
128 {
129 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
130 }
131 else if (configuration->max_hz >= spi_clock / 32)
132 {
133 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
134 }
135 else if (configuration->max_hz >= spi_clock / 64)
136 {
137 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
138 }
139 else if (configuration->max_hz >= spi_clock / 128)
140 {
141 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
142 }
143 else
144 {
145 /* min prescaler 256 */
146 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
147 }
148
149 switch (configuration->mode & RT_SPI_MODE_3)
150 {
151 case RT_SPI_MODE_0:
152 SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
153 SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
154 break;
155 case RT_SPI_MODE_1:
156 SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
157 SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
158 break;
159 case RT_SPI_MODE_2:
160 SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
161 SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
162 break;
163 case RT_SPI_MODE_3:
164 SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
165 SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
166 break;
167 }
168
169 /* MSB or LSB */
170 if (configuration->mode & RT_SPI_MSB)
171 {
172 SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
173 }
174 else
175 {
176 SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_LSB;
177 }
178
179 SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
180 SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
181 SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
182
183 SPI_Init(spi_bus_dev->periph, &SPI_InitStruct);
184 /* Enable SPI_MASTER */
185 SPI_Cmd(spi_bus_dev->periph, ENABLE);
186
187 return RT_EOK;
188 };
189
air32_spi_xfer(struct rt_spi_device * device,struct rt_spi_message * message)190 static rt_uint32_t air32_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
191 {
192 struct rt_spi_bus *spi_bus;
193 struct spi_bus_device *spi_bus_dev;
194 struct rt_spi_configuration *config;
195
196 RT_ASSERT(device != NULL);
197 RT_ASSERT(message != NULL);
198
199 //device is not RT_NULL, so spi_bus not need check
200 spi_bus = (struct rt_spi_bus *)device->bus;
201 spi_bus_dev = (struct spi_bus_device *)spi_bus;
202 config = &device->config;
203
204 /* take CS */
205 if (message->cs_take)
206 {
207 rt_pin_write(spi_bus_dev->cs_pin, PIN_LOW);
208 LOG_D("spi take cs\n");
209 }
210
211 if (config->data_width <= 8)
212 {
213 const rt_uint8_t *send_ptr = message->send_buf;
214 rt_uint8_t *recv_ptr = message->recv_buf;
215 rt_uint32_t size = message->length;
216 rt_uint8_t data;
217
218 LOG_D("spi poll transfer start: %d\n", size);
219
220 while (size--)
221 {
222 data = 0xFF;
223
224 if (send_ptr != RT_NULL)
225 {
226 data = *send_ptr++;
227 }
228
229 //Wait until the transmit buffer is empty
230 while (SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_TXE) == RESET);
231 // Send the byte
232 SPI_I2S_SendData(spi_bus_dev->periph, data);
233
234 //Wait until a data is received
235 while (SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_RXNE) == RESET);
236 // Get the received data
237 data = SPI_I2S_ReceiveData(spi_bus_dev->periph);
238
239 if (recv_ptr != RT_NULL)
240 {
241 *recv_ptr++ = data;
242 }
243 }
244 LOG_D("spi poll transfer finsh\n");
245 }
246 else if (config->data_width <= 16)
247 {
248 const rt_uint16_t *send_ptr = message->send_buf;
249 rt_uint16_t *recv_ptr = message->recv_buf;
250 rt_uint32_t size = message->length;
251 rt_uint16_t data;
252
253 while (size--)
254 {
255 data = 0xFF;
256
257 if (send_ptr != RT_NULL)
258 {
259 data = *send_ptr++;
260 }
261
262 //Wait until the transmit buffer is empty
263 while (RESET == SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_TXE))
264 ;
265 // Send the byte
266 SPI_I2S_SendData(spi_bus_dev->periph, data);
267
268 //Wait until a data is received
269 while (RESET == SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_RXNE))
270 ;
271 // Get the received data
272 data = SPI_I2S_ReceiveData(spi_bus_dev->periph);
273
274 if (recv_ptr != RT_NULL)
275 {
276 *recv_ptr++ = data;
277 }
278 }
279 }
280
281 /* release CS */
282 if (message->cs_release)
283 {
284 rt_pin_write(spi_bus_dev->cs_pin, PIN_HIGH);
285 LOG_D("spi release cs\n");
286 }
287
288 return message->length;
289 };
290
291 static struct rt_spi_ops spi_ops = {
292 .configure = air32_spi_configure,
293 .xfer = air32_spi_xfer};
294
rt_hw_spi_init(void)295 int rt_hw_spi_init(void)
296 {
297 int index;
298
299 for (index = 0; index < ITEM_NUM(spi_bus_device_list); index++)
300 {
301 rt_spi_bus_register(&spi_bus_device_list[index].parent, spi_bus_device_list[index].name, &spi_ops);
302 }
303
304 return RT_EOK;
305 }
306
307 INIT_BOARD_EXPORT(rt_hw_spi_init);
308
309 #endif /* BSP_USING_SPI */
310