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