1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date             Author          Notes
8  * 2020-05-22       Sherman         first version
9  * 2020-11-02       xckhmf          fixed bug
10  * 2023-01-28       Andrew          add Nrf5340 support
11  */
12 
13 #include <stdint.h>
14 #include <string.h>
15 #include "board.h"
16 #include "drv_spi.h"
17 
18 #define DBG_LEVEL   DBG_LOG
19 #include <rtdbg.h>
20 #define LOG_TAG                "drv.spi"
21 
22 #ifdef BSP_USING_SPI
23 #if defined(SOC_NRF5340)
24 #if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) || defined(BSP_USING_SPI4)
25 static struct nrfx_drv_spi_config spi_config[] =
26 {
27 #ifdef BSP_USING_SPI0
28     NRFX_SPI0_CONFIG,
29 #endif
30 
31 #ifdef BSP_USING_SPI1
32     NRFX_SPI1_CONFIG,
33 #endif
34 
35 #ifdef BSP_USING_SPI2
36     NRFX_SPI2_CONFIG,
37 #endif
38 
39 #ifdef BSP_USING_SPI3
40     NRFX_SPI3_CONFIG,
41 #endif
42 
43 #ifdef BSP_USING_SPI4
44     NRFX_SPI4_CONFIG,
45 #endif
46 
47 
48 };
49 
50 static struct nrfx_drv_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])];
51 
52 /* Configure SPI bus pins using the menuconfig */
53 static struct nrfx_drv_spi_pin_config bsp_spi_pin[] =
54 {
55 #ifdef BSP_USING_SPI0
56     {
57         .sck_pin = BSP_SPI0_SCK_PIN,
58         .mosi_pin = BSP_SPI0_MOSI_PIN,
59         .miso_pin = BSP_SPI0_MISO_PIN,
60         .ss_pin = BSP_SPI0_SS_PIN
61     },
62 #endif
63 
64 #ifdef BSP_USING_SPI1
65     {
66         .sck_pin = BSP_SPI1_SCK_PIN,
67         .mosi_pin = BSP_SPI1_MOSI_PIN,
68         .miso_pin = BSP_SPI1_MISO_PIN,
69         .ss_pin = BSP_SPI1_SS_PIN
70     },
71 #endif
72 
73 #ifdef BSP_USING_SPI2
74     {
75         .sck_pin = BSP_SPI2_SCK_PIN,
76         .mosi_pin = BSP_SPI2_MOSI_PIN,
77         .miso_pin = BSP_SPI2_MISO_PIN,
78         .ss_pin = BSP_SPI2_SS_PIN
79     },
80 #endif
81 
82 #ifdef BSP_USING_SPI3
83     {
84         .sck_pin = BSP_SPI3_SCK_PIN,
85         .mosi_pin = BSP_SPI3_MOSI_PIN,
86         .miso_pin = BSP_SPI3_MISO_PIN,
87         .ss_pin = BSP_SPI3_SS_PIN
88     },
89 #endif
90 
91 #ifdef BSP_USING_SPI4
92     {
93         .sck_pin = BSP_SPI4_SCK_PIN,
94         .mosi_pin = BSP_SPI4_MOSI_PIN,
95         .miso_pin = BSP_SPI4_MISO_PIN,
96         .ss_pin = BSP_SPI4_SS_PIN
97     },
98 #endif
99 
100 
101 };
102 
103 
spi_index_find(struct rt_spi_bus * spi_bus)104 static rt_uint8_t spi_index_find(struct rt_spi_bus *spi_bus)
105 {
106     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
107     {
108         if(spi_bus == &spi_bus_obj[i].spi_bus)
109             return i;
110     }
111     return 0xFF;
112 }
113 
114 /**
115  * spi event handler function
116  */
spi0_handler(const nrfx_spim_evt_t * p_event,void * p_context)117 static void spi0_handler(const nrfx_spim_evt_t *p_event, void *p_context)
118 {
119     LOG_I("\nspi0_handler");
120 }
121 
spi1_handler(const nrfx_spim_evt_t * p_event,void * p_context)122 static void spi1_handler(const nrfx_spim_evt_t *p_event, void *p_context)
123 {
124     LOG_I("\nspi1_handler");
125 }
126 
spi2_handler(const nrfx_spim_evt_t * p_event,void * p_context)127 static void spi2_handler(const nrfx_spim_evt_t *p_event, void *p_context)
128 {
129     LOG_I("\nspi2_handler");
130 }
131 
spi3_handler(const nrfx_spim_evt_t * p_event,void * p_context)132 static void spi3_handler(const nrfx_spim_evt_t *p_event, void *p_context)
133 {
134     LOG_I("\nspi3_handler");
135 }
136 
spi4_handler(const nrfx_spim_evt_t * p_event,void * p_context)137 static void spi4_handler(const nrfx_spim_evt_t *p_event, void *p_context)
138 {
139     LOG_I("\nspi4_handler");
140 }
141 
142 
143 nrfx_spim_evt_handler_t spi_handler[] = {spi0_handler, spi1_handler, spi2_handler ,spi3_handler,spi4_handler};
144 
145 /**
146   * @brief  This function config spi bus
147   * @param  device
148   * @param  configuration
149   * @retval RT_EOK / -RT_ERROR
150   */
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)151 static rt_err_t spi_configure(struct rt_spi_device *device,
152                               struct rt_spi_configuration *configuration)
153 {
154     RT_ASSERT(device != RT_NULL);
155     RT_ASSERT(device->bus != RT_NULL);
156     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
157     RT_ASSERT(configuration != RT_NULL);
158 
159     rt_uint8_t index = spi_index_find(device->bus);
160     RT_ASSERT(index != 0xFF);
161 
162     nrfx_spim_t spi = spi_bus_obj[index].spi;
163     nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG(bsp_spi_pin[index].sck_pin,
164         bsp_spi_pin[index].mosi_pin, bsp_spi_pin[index].miso_pin, NRFX_SPIM_PIN_NOT_USED);
165 
166     /* spi config ss pin */
167     if(device->parent.user_data != RT_NULL)
168     {
169         nrf_gpio_cfg_output((uint32_t)device->parent.user_data);
170     }
171     /* spi config bit order */
172     if(configuration->mode & RT_SPI_MSB)
173     {
174         config.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
175     }
176     else
177     {
178         config.bit_order = NRF_SPIM_BIT_ORDER_LSB_FIRST;
179     }
180     /* spi mode config */
181     switch (configuration->mode & RT_SPI_MODE_3 )
182     {
183     case RT_SPI_MODE_0/* RT_SPI_CPOL:0 , RT_SPI_CPHA:0 */:
184         config.mode = NRF_SPIM_MODE_0;
185         break;
186     case RT_SPI_MODE_1/* RT_SPI_CPOL:0 , RT_SPI_CPHA:1 */:
187         config.mode = NRF_SPIM_MODE_1;
188         break;
189     case RT_SPI_MODE_2/* RT_SPI_CPOL:1 , RT_SPI_CPHA:0 */:
190         config.mode = NRF_SPIM_MODE_2;
191         break;
192     case RT_SPI_MODE_3/* RT_SPI_CPOL:1 , RT_SPI_CPHA:1 */:
193         config.mode = NRF_SPIM_MODE_3;
194         break;
195     default:
196         LOG_E("spi_configure mode error %x\n",configuration->mode);
197         return -RT_ERROR;
198     }
199     /* spi frequency config */
200     switch (configuration->max_hz / 1000)
201     {
202     case 125:
203         config.frequency = NRF_SPIM_FREQ_125K;
204         break;
205     case 250:
206         config.frequency = NRF_SPIM_FREQ_250K;
207         break;
208     case 500:
209         config.frequency = NRF_SPIM_FREQ_500K;
210         break;
211     case 1000:
212         config.frequency = NRF_SPIM_FREQ_1M;
213         break;
214     case 2000:
215         config.frequency = NRF_SPIM_FREQ_2M;
216         break;
217     case 4000:
218         config.frequency = NRF_SPIM_FREQ_4M;
219         break;
220     case 8000:
221         config.frequency = NRF_SPIM_FREQ_8M;
222         break;
223     default:
224         LOG_E("spi_configure rate error %d\n",configuration->max_hz);
225         break;
226     }
227 
228     rt_memcpy((void*)&spi_bus_obj[index].spi_config, (void*)&config, sizeof(nrfx_spim_config_t));
229     nrfx_spim_evt_handler_t handler = RT_NULL;    /* spi send callback handler ,default NULL */
230     void * context = RT_NULL;
231     nrfx_err_t nrf_ret = nrfx_spim_init(&spi, &config, handler, context);
232     if(NRFX_SUCCESS == nrf_ret)
233         return RT_EOK;
234 
235     return -RT_ERROR;
236 }
237 
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)238 static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
239 {
240     RT_ASSERT(device != RT_NULL);
241     RT_ASSERT(device->bus != RT_NULL);
242     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
243 
244     rt_uint8_t index = spi_index_find(device->bus);
245     nrfx_err_t nrf_ret;
246     RT_ASSERT(index != 0xFF);
247 
248     nrfx_spim_t * p_instance =  &spi_bus_obj[index].spi;
249     nrfx_spim_xfer_desc_t p_xfer_desc;
250 
251     if(message->cs_take == 1)
252     {
253         nrf_gpio_pin_clear((uint32_t)device->parent.user_data);
254     }
255     p_xfer_desc.p_rx_buffer = message->recv_buf;
256     p_xfer_desc.rx_length = message->length;
257     p_xfer_desc.p_tx_buffer = message->send_buf;
258     p_xfer_desc.tx_length = message->length ;
259     if(message->send_buf == RT_NULL)
260     {
261         p_xfer_desc.tx_length = 0;
262     }
263 
264     if(message->recv_buf == RT_NULL)
265     {
266         p_xfer_desc.rx_length = 0;
267     }
268 
269     nrf_ret = nrfx_spim_xfer(p_instance, &p_xfer_desc, 0);
270     if(message->cs_release == 1)
271     {
272         nrf_gpio_pin_set((uint32_t)device->parent.user_data);
273     }
274 
275     if( NRFX_SUCCESS != nrf_ret)
276     {
277         return 0;
278     }
279     else
280     {
281         return message->length;
282     }
283 }
284 
285 /* spi bus callback function  */
286 static const struct rt_spi_ops nrfx_spi_ops =
287 {
288     .configure = spi_configure,
289     .xfer = spixfer,
290 };
291 
292 /*spi bus init*/
rt_hw_spi_bus_init(void)293 static int rt_hw_spi_bus_init(void)
294 {
295     rt_err_t result = -RT_ERROR;
296     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
297     {
298         spi_bus_obj[i].spi = spi_config[i].spi;
299         spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   /* SPI INSTANCE */
300         result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &nrfx_spi_ops);
301         RT_ASSERT(result == RT_EOK);
302     }
303     return result;
304 }
305 
rt_hw_spi_init(void)306 int rt_hw_spi_init(void)
307 {
308     return rt_hw_spi_bus_init();
309 }
310 INIT_BOARD_EXPORT(rt_hw_spi_init);
311 
312 /**
313   * Attach the spi device to SPI bus, this function must be used after initialization.
314   */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_uint32_t ss_pin)315 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin)
316 {
317     RT_ASSERT(bus_name != RT_NULL);
318     RT_ASSERT(device_name != RT_NULL);
319     RT_ASSERT(ss_pin != RT_NULL);
320 
321     rt_err_t result;
322     struct rt_spi_device *spi_device;
323     /* attach the device to spi bus*/
324     spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
325     RT_ASSERT(spi_device != RT_NULL);
326     /* initialize the cs pin */
327     result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void*)ss_pin);
328     if (result != RT_EOK)
329     {
330         LOG_E("%s attach to %s faild, %d", device_name, bus_name, result);
331         result = -RT_ERROR;
332     }
333     RT_ASSERT(result == RT_EOK);
334     return result;
335 }
336 
337 #define SPI_DEVICE_NAME     "spi4x"
338 #define TEST_STRING "liguan"
339 static rt_uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
340 
spi_sample(int argc,char * argv[])341 static int spi_sample(int argc, char *argv[])
342 
343 {
344     struct rt_spi_device *spi_dev;
345     char name[RT_NAME_MAX];
346     rt_uint8_t w25x_read_id = 0x65;
347     rt_uint8_t id[5] = {0};
348     rt_hw_spi_device_attach("spi4", SPI_DEVICE_NAME, 11);
349     struct rt_spi_configuration cfg;
350     cfg.data_width = 8;
351     cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
352     cfg.max_hz = 20 * 1000 *1000;                           /* 20M */
353 
354 
355 
356     /* find spi device to get handler */
357     spi_dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
358     if (!spi_dev)
359     {
360         rt_kprintf("spi sample run failed! can't find %s device!\n", name);
361     }
362     else
363     {
364          rt_spi_configure(spi_dev, &cfg);
365         /* use func: rt_spi_send_then_recv() send and read ID */
366          while(1)
367        { rt_spi_send(spi_dev, m_tx_buf, 6);rt_thread_mdelay(500);}
368         /* rt_kprintf("use rt_spi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]); */
369         }
370 return RT_EOK;
371 
372 }
373 MSH_CMD_EXPORT(spi_sample, spi sample);
374 #endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */
375 #else
376 #if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2)
377 static struct nrfx_drv_spi_config spi_config[] =
378 {
379 #ifdef BSP_USING_SPI0
380     NRFX_SPI0_CONFIG,
381 #endif
382 
383 #ifdef BSP_USING_SPI1
384     NRFX_SPI1_CONFIG,
385 #endif
386 
387 #ifdef BSP_USING_SPI2
388     NRFX_SPI2_CONFIG,
389 #endif
390 
391 };
392 
393 static struct nrfx_drv_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])];
394 
395 /* Configure SPI bus pins using the menuconfig */
396 static struct nrfx_drv_spi_pin_config bsp_spi_pin[] =
397 {
398 #ifdef BSP_USING_SPI0
399     {
400         .sck_pin = BSP_SPI0_SCK_PIN,
401         .mosi_pin = BSP_SPI0_MOSI_PIN,
402         .miso_pin = BSP_SPI0_MISO_PIN,
403         .ss_pin = BSP_SPI0_SS_PIN
404     },
405 #endif
406 
407 #ifdef BSP_USING_SPI1
408     {
409         .sck_pin = BSP_SPI1_SCK_PIN,
410         .mosi_pin = BSP_SPI1_MOSI_PIN,
411         .miso_pin = BSP_SPI1_MISO_PIN,
412         .ss_pin = BSP_SPI1_SS_PIN
413     },
414 #endif
415 
416 #ifdef BSP_USING_SPI2
417     {
418         .sck_pin = BSP_SPI2_SCK_PIN,
419         .mosi_pin = BSP_SPI2_MOSI_PIN,
420         .miso_pin = BSP_SPI2_MISO_PIN,
421         .ss_pin = BSP_SPI2_SS_PIN
422     },
423 #endif
424 };
425 
426 
spi_index_find(struct rt_spi_bus * spi_bus)427 static rt_uint8_t spi_index_find(struct rt_spi_bus *spi_bus)
428 {
429     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
430     {
431         if(spi_bus == &spi_bus_obj[i].spi_bus)
432             return i;
433     }
434     return 0xFF;
435 }
436 
437 /**
438  * spi event handler function
439  */
spi0_handler(const nrfx_spi_evt_t * p_event,void * p_context)440 static void spi0_handler(const nrfx_spi_evt_t *p_event, void *p_context)
441 {
442     LOG_I("\nspi0_handler");
443 }
444 
spi1_handler(const nrfx_spi_evt_t * p_event,void * p_context)445 static void spi1_handler(const nrfx_spi_evt_t *p_event, void *p_context)
446 {
447     LOG_I("\nspi1_handler");
448 }
449 
spi2_handler(const nrfx_spi_evt_t * p_event,void * p_context)450 static void spi2_handler(const nrfx_spi_evt_t *p_event, void *p_context)
451 {
452     LOG_I("\nspi2_handler");
453 }
454 nrfx_spi_evt_handler_t spi_handler[] = {spi0_handler, spi1_handler, spi2_handler};
455 
456 /**
457   * @brief  This function config spi bus
458   * @param  device
459   * @param  configuration
460   * @retval RT_EOK / -RT_ERROR
461   */
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)462 static rt_err_t spi_configure(struct rt_spi_device *device,
463                               struct rt_spi_configuration *configuration)
464 {
465     RT_ASSERT(device != RT_NULL);
466     RT_ASSERT(device->bus != RT_NULL);
467     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
468     RT_ASSERT(configuration != RT_NULL);
469 
470     rt_uint8_t index = spi_index_find(device->bus);
471     RT_ASSERT(index != 0xFF);
472 
473     nrfx_spi_t spi = spi_bus_obj[index].spi;
474     nrfx_spi_config_t config = NRFX_SPI_DEFAULT_CONFIG(bsp_spi_pin[index].sck_pin,
475         bsp_spi_pin[index].mosi_pin, bsp_spi_pin[index].miso_pin, NRFX_SPI_PIN_NOT_USED);
476 
477     /* spi config ss pin */
478     if(device->parent.user_data != RT_NULL)
479     {
480         nrf_gpio_cfg_output((uint32_t)device->parent.user_data);
481     }
482     /* spi config bit order */
483     if(configuration->mode & RT_SPI_MSB)
484     {
485         config.bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST;
486     }
487     else
488     {
489         config.bit_order = NRF_SPI_BIT_ORDER_LSB_FIRST;
490     }
491     /* spi mode config */
492     switch (configuration->mode & RT_SPI_MODE_3 )
493     {
494     case RT_SPI_MODE_0/* RT_SPI_CPOL:0 , RT_SPI_CPHA:0 */:
495         config.mode = NRF_SPI_MODE_0;
496         break;
497     case RT_SPI_MODE_1/* RT_SPI_CPOL:0 , RT_SPI_CPHA:1 */:
498         config.mode = NRF_SPI_MODE_1;
499         break;
500     case RT_SPI_MODE_2/* RT_SPI_CPOL:1 , RT_SPI_CPHA:0 */:
501         config.mode = NRF_SPI_MODE_2;
502         break;
503     case RT_SPI_MODE_3/* RT_SPI_CPOL:1 , RT_SPI_CPHA:1 */:
504         config.mode = NRF_SPI_MODE_3;
505         break;
506     default:
507         LOG_E("spi_configure mode error %x\n",configuration->mode);
508         return -RT_ERROR;
509     }
510     /* spi frequency config */
511     switch (configuration->max_hz / 1000)
512     {
513     case 125:
514         config.frequency = NRF_SPI_FREQ_125K;
515         break;
516     case 250:
517         config.frequency = NRF_SPI_FREQ_250K;
518         break;
519     case 500:
520         config.frequency = NRF_SPI_FREQ_500K;
521         break;
522     case 1000:
523         config.frequency = NRF_SPI_FREQ_1M;
524         break;
525     case 2000:
526         config.frequency = NRF_SPI_FREQ_2M;
527         break;
528     case 4000:
529         config.frequency = NRF_SPI_FREQ_4M;
530         break;
531     case 8000:
532         config.frequency = NRF_SPI_FREQ_8M;
533         break;
534     default:
535         LOG_E("spi_configure rate error %d\n",configuration->max_hz);
536         break;
537     }
538 
539     rt_memcpy((void*)&spi_bus_obj[index].spi_config, (void*)&config, sizeof(nrfx_spi_config_t));
540     nrfx_spi_evt_handler_t handler = RT_NULL;    /* spi send callback handler ,default NULL */
541     void * context = RT_NULL;
542     nrfx_err_t nrf_ret = nrfx_spi_init(&spi, &config, handler, context);
543     if(NRFX_SUCCESS == nrf_ret)
544         return RT_EOK;
545 
546     return -RT_ERROR;
547 }
548 
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)549 static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
550 {
551     RT_ASSERT(device != RT_NULL);
552     RT_ASSERT(device->bus != RT_NULL);
553     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
554 
555     rt_uint8_t index = spi_index_find(device->bus);
556     nrfx_err_t nrf_ret;
557     RT_ASSERT(index != 0xFF);
558 
559     nrfx_spi_t * p_instance =  &spi_bus_obj[index].spi;
560     nrfx_spi_xfer_desc_t p_xfer_desc;
561 
562     if(message->cs_take == 1)
563     {
564         nrf_gpio_pin_clear((uint32_t)device->parent.user_data);
565     }
566     p_xfer_desc.p_rx_buffer = message->recv_buf;
567     p_xfer_desc.rx_length = message->length;
568     p_xfer_desc.p_tx_buffer = message->send_buf;
569     p_xfer_desc.tx_length = message->length ;
570     if(message->send_buf == RT_NULL)
571     {
572         p_xfer_desc.tx_length = 0;
573     }
574 
575     if(message->recv_buf == RT_NULL)
576     {
577         p_xfer_desc.rx_length = 0;
578     }
579 
580     nrf_ret = nrfx_spi_xfer(p_instance, &p_xfer_desc, 0);
581     if(message->cs_release == 1)
582     {
583         nrf_gpio_pin_set((uint32_t)device->parent.user_data);
584     }
585 
586     if( NRFX_SUCCESS != nrf_ret)
587     {
588         return 0;
589     }
590     else
591     {
592         return message->length;
593     }
594 }
595 
596 /* spi bus callback function  */
597 static const struct rt_spi_ops nrfx_spi_ops =
598 {
599     .configure = spi_configure,
600     .xfer = spixfer,
601 };
602 
603 /*spi bus init*/
rt_hw_spi_bus_init(void)604 static int rt_hw_spi_bus_init(void)
605 {
606     rt_err_t result = -RT_ERROR;
607     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
608     {
609         spi_bus_obj[i].spi = spi_config[i].spi;
610         spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   /* SPI INSTANCE */
611         result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &nrfx_spi_ops);
612         RT_ASSERT(result == RT_EOK);
613     }
614     return result;
615 }
616 
rt_hw_spi_init(void)617 int rt_hw_spi_init(void)
618 {
619     return rt_hw_spi_bus_init();
620 }
621 INIT_BOARD_EXPORT(rt_hw_spi_init);
622 
623 /**
624   * Attach the spi device to SPI bus, this function must be used after initialization.
625   */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_uint32_t ss_pin)626 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin)
627 {
628     RT_ASSERT(bus_name != RT_NULL);
629     RT_ASSERT(device_name != RT_NULL);
630     RT_ASSERT(ss_pin != RT_NULL);
631 
632     rt_err_t result;
633     struct rt_spi_device *spi_device;
634     /* attach the device to spi bus*/
635     spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
636     RT_ASSERT(spi_device != RT_NULL);
637     /* initialize the cs pin */
638     result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void*)ss_pin);
639     if (result != RT_EOK)
640     {
641         LOG_E("%s attach to %s faild, %d", device_name, bus_name, result);
642         result = -RT_ERROR;
643     }
644     RT_ASSERT(result == RT_EOK);
645     return result;
646 }
647 
648 #endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */
649 #endif
650 #endif /*BSP_USING_SPI*/
651 
652