1 /**************************************************************************//**
2 *
3 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date            Author           Notes
9 * 2020-2-27       YHKuo            First version
10 *
11 ******************************************************************************/
12 #include <rtconfig.h>
13 
14 #if defined(BSP_USING_SPI)
15 
16 #define LOG_TAG                 "drv.spi"
17 #define DBG_ENABLE
18 #define DBG_SECTION_NAME        LOG_TAG
19 #define DBG_LEVEL               DBG_INFO
20 #define DBG_COLOR
21 #include <rtdbg.h>
22 
23 #include <rthw.h>
24 #include <rtdevice.h>
25 #include <rtdef.h>
26 
27 #include <drv_spi.h>
28 
29 
30 /* Private define ---------------------------------------------------------------*/
31 
32 #ifndef NU_SPI_USE_PDMA_MIN_THRESHOLD
33     #define NU_SPI_USE_PDMA_MIN_THRESHOLD (128)
34 #endif
35 
36 enum
37 {
38     SPI_START = -1,
39 #if defined(BSP_USING_SPI0)
40     SPI0_IDX,
41 #endif
42 #if defined(BSP_USING_SPI1)
43     SPI1_IDX,
44 #endif
45 #if defined(BSP_USING_SPI2)
46     SPI2_IDX,
47 #endif
48 #if defined(BSP_USING_SPI3)
49     SPI3_IDX,
50 #endif
51     SPI_CNT
52 };
53 
54 /* Private typedef --------------------------------------------------------------*/
55 
56 /* Private functions ------------------------------------------------------------*/
57 static void nu_spi_transmission_with_poll(struct nu_spi *spi_bus,
58         uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
59 static int nu_spi_register_bus(struct nu_spi *spi_bus, const char *name);
60 static rt_ssize_t nu_spi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
61 static rt_err_t nu_spi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
62 
63 #if defined(BSP_USING_SPI_PDMA)
64     static void nu_pdma_spi_rx_cb(void *pvUserData, uint32_t u32EventFilter);
65     static rt_err_t nu_pdma_spi_rx_config(struct nu_spi *spi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word);
66     static rt_err_t nu_pdma_spi_tx_config(struct nu_spi *spi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word);
67     static rt_ssize_t nu_spi_pdma_transmit(struct nu_spi *spi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
68 #endif
69 /* Public functions -------------------------------------------------------------*/
70 void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word);
71 void nu_spi_drain_rxfifo(SPI_T *spi_base);
72 
73 /* Private variables ------------------------------------------------------------*/
74 static struct rt_spi_ops nu_spi_poll_ops =
75 {
76     .configure = nu_spi_bus_configure,
77     .xfer      = nu_spi_bus_xfer,
78 };
79 
80 static struct nu_spi nu_spi_arr [] =
81 {
82 #if defined(BSP_USING_SPI0)
83     {
84         .name = "spi0",
85         .spi_base = SPI0,
86 
87 #if defined(BSP_USING_SPI_PDMA)
88 #if defined(BSP_USING_SPI0_PDMA)
89         .pdma_perp_tx = PDMA_SPI0_TX,
90         .pdma_perp_rx = PDMA_SPI0_RX,
91 #else
92         .pdma_perp_tx = NU_PDMA_UNUSED,
93         .pdma_perp_rx = NU_PDMA_UNUSED,
94 #endif
95 #endif
96     },
97 #endif
98 #if defined(BSP_USING_SPI1)
99     {
100         .name = "spi1",
101         .spi_base = SPI1,
102 
103 #if defined(BSP_USING_SPI_PDMA)
104 #if defined(BSP_USING_SPI1_PDMA)
105         .pdma_perp_tx = PDMA_SPI1_TX,
106         .pdma_perp_rx = PDMA_SPI1_RX,
107 #else
108         .pdma_perp_tx = NU_PDMA_UNUSED,
109         .pdma_perp_rx = NU_PDMA_UNUSED,
110 #endif
111 #endif
112 
113     },
114 #endif
115 #if defined(BSP_USING_SPI2)
116     {
117         .name = "spi2",
118         .spi_base = SPI2,
119 
120 #if defined(BSP_USING_SPI_PDMA)
121 #if defined(BSP_USING_SPI2_PDMA)
122         .pdma_perp_tx = PDMA_SPI2_TX,
123         .pdma_perp_rx = PDMA_SPI2_RX,
124 #else
125         .pdma_perp_tx = NU_PDMA_UNUSED,
126         .pdma_perp_rx = NU_PDMA_UNUSED,
127 #endif
128 #endif
129 
130     },
131 #endif
132 #if defined(BSP_USING_SPI3)
133     {
134         .name = "spi3",
135         .spi_base = SPI3,
136 
137 #if defined(BSP_USING_SPI_PDMA)
138 #if defined(BSP_USING_SPI3_PDMA)
139         .pdma_perp_tx = PDMA_SPI3_TX,
140         .pdma_perp_rx = PDMA_SPI3_RX,
141 #else
142         .pdma_perp_tx = NU_PDMA_UNUSED,
143         .pdma_perp_rx = NU_PDMA_UNUSED,
144 #endif
145 #endif
146 
147     },
148 #endif
149     {0}
150 }; /* spi nu_spi */
151 
nu_spi_bus_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)152 static rt_err_t nu_spi_bus_configure(struct rt_spi_device *device,
153                                      struct rt_spi_configuration *configuration)
154 {
155     struct nu_spi *spi_bus;
156     uint32_t u32SPIMode;
157     uint32_t u32BusClock;
158     rt_err_t ret = RT_EOK;
159     void *pvUserData;
160 
161     RT_ASSERT(device != RT_NULL);
162     RT_ASSERT(configuration != RT_NULL);
163 
164     spi_bus = (struct nu_spi *) device->bus;
165     pvUserData = device->parent.user_data;
166 
167     /* Check mode */
168     switch (configuration->mode & RT_SPI_MODE_3)
169     {
170     case RT_SPI_MODE_0:
171         u32SPIMode = SPI_MODE_0;
172         break;
173     case RT_SPI_MODE_1:
174         u32SPIMode = SPI_MODE_1;
175         break;
176     case RT_SPI_MODE_2:
177         u32SPIMode = SPI_MODE_2;
178         break;
179     case RT_SPI_MODE_3:
180         u32SPIMode = SPI_MODE_3;
181         break;
182     default:
183         ret = -RT_EIO;
184         goto exit_nu_spi_bus_configure;
185     }
186 
187     /* Check data width */
188     if (!(configuration->data_width == 8  ||
189             configuration->data_width == 16 ||
190             configuration->data_width == 24 ||
191             configuration->data_width == 32))
192     {
193         ret = -RT_EINVAL;
194         goto exit_nu_spi_bus_configure;
195     }
196 
197     /* Try to set clock and get actual spi bus clock */
198     u32BusClock = SPI_SetBusClock(spi_bus->spi_base, configuration->max_hz);
199     if (configuration->max_hz > u32BusClock)
200     {
201         LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", spi_bus->name, u32BusClock, configuration->max_hz);
202         configuration->max_hz = u32BusClock;
203     }
204 
205     /* Need to initialize new configuration? */
206     if (rt_memcmp(configuration, &spi_bus->configuration, sizeof(*configuration)) != 0)
207     {
208         rt_memcpy(&spi_bus->configuration, configuration, sizeof(*configuration));
209 
210         SPI_Open(spi_bus->spi_base, SPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock);
211 
212         if (configuration->mode & RT_SPI_CS_HIGH)
213         {
214             /* Set CS pin to LOW */
215             if (pvUserData != RT_NULL)
216             {
217                 // set to LOW */
218                 rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
219             }
220             else
221             {
222                 SPI_SET_SS_LOW(spi_bus->spi_base);
223             }
224         }
225         else
226         {
227             /* Set CS pin to HIGH */
228             if (pvUserData != RT_NULL)
229             {
230                 // set to HIGH */
231                 rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
232             }
233             else
234             {
235                 /* Set CS pin to HIGH */
236                 SPI_SET_SS_HIGH(spi_bus->spi_base);
237             }
238         }
239 
240         if (configuration->mode & RT_SPI_MSB)
241         {
242             /* Set sequence to MSB first */
243             SPI_SET_MSB_FIRST(spi_bus->spi_base);
244         }
245         else
246         {
247             /* Set sequence to LSB first */
248             SPI_SET_LSB_FIRST(spi_bus->spi_base);
249         }
250     }
251 
252     /* Clear SPI RX FIFO */
253     nu_spi_drain_rxfifo(spi_bus->spi_base);
254 
255 exit_nu_spi_bus_configure:
256 
257     return -(ret);
258 }
259 
260 #if defined(BSP_USING_SPI_PDMA)
nu_pdma_spi_rx_cb(void * pvUserData,uint32_t u32EventFilter)261 static void nu_pdma_spi_rx_cb(void *pvUserData, uint32_t u32EventFilter)
262 {
263     rt_err_t result;
264     struct nu_spi *spi_bus = (struct nu_spi *)pvUserData;
265 
266     RT_ASSERT(spi_bus != RT_NULL);
267 
268     result = rt_sem_release(spi_bus->m_psSemBus);
269     RT_ASSERT(result == RT_EOK);
270 }
nu_pdma_spi_rx_config(struct nu_spi * spi_bus,uint8_t * pu8Buf,int32_t i32RcvLen,uint8_t bytes_per_word)271 static rt_err_t nu_pdma_spi_rx_config(struct nu_spi *spi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word)
272 {
273     rt_err_t result = RT_EOK;
274     rt_uint8_t *dst_addr = NULL;
275     nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
276 
277     /* Get base address of spi register */
278     SPI_T *spi_base = spi_bus->spi_base;
279 
280     rt_uint8_t spi_pdma_rx_chid = spi_bus->pdma_chanid_rx;
281 
282     result = nu_pdma_callback_register(spi_pdma_rx_chid,
283                                        nu_pdma_spi_rx_cb,
284                                        (void *)spi_bus,
285                                        NU_PDMA_EVENT_TRANSFER_DONE);
286     if (result != RT_EOK)
287     {
288         goto exit_nu_pdma_spi_rx_config;
289     }
290 
291     if (pu8Buf == RT_NULL)
292     {
293         memctrl  = eMemCtl_SrcFix_DstFix;
294         dst_addr = (rt_uint8_t *) &spi_bus->dummy;
295     }
296     else
297     {
298         memctrl  = eMemCtl_SrcFix_DstInc;
299         dst_addr = pu8Buf;
300     }
301 
302     result = nu_pdma_channel_memctrl_set(spi_pdma_rx_chid, memctrl);
303     if (result != RT_EOK)
304     {
305         goto exit_nu_pdma_spi_rx_config;
306     }
307 
308     result = nu_pdma_transfer(spi_pdma_rx_chid,
309                               bytes_per_word * 8,
310                               (uint32_t)&spi_base->RX,
311                               (uint32_t)dst_addr,
312                               i32RcvLen / bytes_per_word,
313                               0);
314 exit_nu_pdma_spi_rx_config:
315 
316     return result;
317 }
318 
nu_pdma_spi_tx_config(struct nu_spi * spi_bus,const uint8_t * pu8Buf,int32_t i32SndLen,uint8_t bytes_per_word)319 static rt_err_t nu_pdma_spi_tx_config(struct nu_spi *spi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word)
320 {
321     rt_err_t result = RT_EOK;
322     rt_uint8_t *src_addr = NULL;
323     nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
324 
325     /* Get base address of spi register */
326     SPI_T *spi_base = spi_bus->spi_base;
327 
328     rt_uint8_t spi_pdma_tx_chid = spi_bus->pdma_chanid_tx;
329 
330     if (pu8Buf == RT_NULL)
331     {
332         spi_bus->dummy = 0;
333         memctrl = eMemCtl_SrcFix_DstFix;
334         src_addr = (rt_uint8_t *)&spi_bus->dummy;
335     }
336     else
337     {
338         memctrl = eMemCtl_SrcInc_DstFix;
339         src_addr = (rt_uint8_t *)pu8Buf;
340     }
341 
342     result = nu_pdma_channel_memctrl_set(spi_pdma_tx_chid, memctrl);
343     if (result != RT_EOK)
344     {
345         goto exit_nu_pdma_spi_tx_config;
346     }
347 
348     result = nu_pdma_transfer(spi_pdma_tx_chid,
349                               bytes_per_word * 8,
350                               (uint32_t)src_addr,
351                               (uint32_t)&spi_base->TX,
352                               i32SndLen / bytes_per_word,
353                               0);
354 exit_nu_pdma_spi_tx_config:
355 
356     return result;
357 }
358 
359 
360 /**
361  * SPI PDMA transfer
362  */
nu_spi_pdma_transmit(struct nu_spi * spi_bus,const uint8_t * send_addr,uint8_t * recv_addr,int length,uint8_t bytes_per_word)363 static rt_ssize_t nu_spi_pdma_transmit(struct nu_spi *spi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
364 {
365     rt_err_t result = RT_EOK;
366     rt_uint32_t u32Offset = 0;
367     rt_uint32_t u32TransferCnt = length / bytes_per_word;
368     rt_uint32_t u32TxCnt = 0;
369 
370     /* Get base address of spi register */
371     SPI_T *spi_base = spi_bus->spi_base;
372 
373     do
374     {
375         u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt;
376         result = nu_pdma_spi_rx_config(spi_bus, (recv_addr == RT_NULL) ? recv_addr : &recv_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
377         RT_ASSERT(result == RT_EOK);
378 
379         result = nu_pdma_spi_tx_config(spi_bus, (send_addr == RT_NULL) ? send_addr : &send_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
380         RT_ASSERT(result == RT_EOK);
381 
382         /* Trigger TX/RX PDMA transfer. */
383         SPI_TRIGGER_TX_RX_PDMA(spi_base);
384 
385         /* Wait RX-PDMA transfer done */
386         result = rt_sem_take(spi_bus->m_psSemBus, RT_WAITING_FOREVER);
387         RT_ASSERT(result == RT_EOK);
388 
389         /* Stop TX/RX DMA transfer. */
390         SPI_DISABLE_TX_RX_PDMA(spi_base);
391 
392         u32TransferCnt -= u32TxCnt;
393         u32Offset += u32TxCnt;
394 
395     }
396     while (u32TransferCnt > 0);
397 
398     return length;
399 }
400 
nu_hw_spi_pdma_allocate(struct nu_spi * spi_bus)401 rt_err_t nu_hw_spi_pdma_allocate(struct nu_spi *spi_bus)
402 {
403     /* Allocate SPI_TX nu_dma channel */
404     if ((spi_bus->pdma_chanid_tx = nu_pdma_channel_allocate(spi_bus->pdma_perp_tx)) < 0)
405     {
406         goto exit_nu_hw_spi_pdma_allocate;
407     }
408     /* Allocate SPI_RX nu_dma channel */
409     else if ((spi_bus->pdma_chanid_rx = nu_pdma_channel_allocate(spi_bus->pdma_perp_rx)) < 0)
410     {
411         nu_pdma_channel_free(spi_bus->pdma_chanid_tx);
412         goto exit_nu_hw_spi_pdma_allocate;
413     }
414 
415     spi_bus->m_psSemBus = rt_sem_create("spibus_sem", 0, RT_IPC_FLAG_FIFO);
416     RT_ASSERT(spi_bus->m_psSemBus != RT_NULL);
417 
418     return RT_EOK;
419 
420 exit_nu_hw_spi_pdma_allocate:
421 
422     return -(RT_ERROR);
423 }
424 #endif /* #if defined(BSP_USING_SPI_PDMA) */
425 
nu_spi_drain_rxfifo(SPI_T * spi_base)426 void nu_spi_drain_rxfifo(SPI_T *spi_base)
427 {
428     while (SPI_IS_BUSY(spi_base));
429 
430     // Drain SPI RX FIFO, make sure RX FIFO is empty
431     while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
432     {
433         SPI_ClearRxFIFO(spi_base);
434     }
435 }
436 
nu_spi_read(SPI_T * spi_base,uint8_t * recv_addr,uint8_t bytes_per_word)437 static int nu_spi_read(SPI_T *spi_base, uint8_t *recv_addr, uint8_t bytes_per_word)
438 {
439     int size = 0;
440 
441     // Read RX data
442     if (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
443     {
444         uint32_t val;
445         // Read data from SPI RX FIFO
446         switch (bytes_per_word)
447         {
448         case 4:
449             val = SPI_READ_RX(spi_base);
450             nu_set32_le(recv_addr, val);
451             break;
452         case 3:
453             val = SPI_READ_RX(spi_base);
454             nu_set24_le(recv_addr, val);
455             break;
456         case 2:
457             val = SPI_READ_RX(spi_base);
458             nu_set16_le(recv_addr, val);
459             break;
460         case 1:
461             *recv_addr = SPI_READ_RX(spi_base);
462             break;
463         default:
464             LOG_E("Data length is not supported.\n");
465             break;
466         }
467         size = bytes_per_word;
468     }
469     return size;
470 }
471 
nu_spi_write(SPI_T * spi_base,const uint8_t * send_addr,uint8_t bytes_per_word)472 static int nu_spi_write(SPI_T *spi_base, const uint8_t *send_addr, uint8_t bytes_per_word)
473 {
474     // Wait SPI TX send data
475     while (SPI_GET_TX_FIFO_FULL_FLAG(spi_base));
476 
477     // Input data to SPI TX
478     switch (bytes_per_word)
479     {
480     case 4:
481         SPI_WRITE_TX(spi_base, nu_get32_le(send_addr));
482         break;
483     case 3:
484         SPI_WRITE_TX(spi_base, nu_get24_le(send_addr));
485         break;
486     case 2:
487         SPI_WRITE_TX(spi_base, nu_get16_le(send_addr));
488         break;
489     case 1:
490         SPI_WRITE_TX(spi_base, *((uint8_t *)send_addr));
491         break;
492     default:
493         LOG_E("Data length is not supported.\n");
494         break;
495     }
496 
497     return bytes_per_word;
498 }
499 
500 /**
501  * @brief SPI bus polling
502  * @param dev : The pointer of the specified SPI module.
503  * @param send_addr : Source address
504  * @param recv_addr : Destination address
505  * @param length    : Data length
506  */
nu_spi_transmission_with_poll(struct nu_spi * spi_bus,uint8_t * send_addr,uint8_t * recv_addr,int length,uint8_t bytes_per_word)507 static void nu_spi_transmission_with_poll(struct nu_spi *spi_bus,
508         uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
509 {
510     SPI_T *spi_base = spi_bus->spi_base;
511 
512     // Write-only
513     if ((send_addr != RT_NULL) && (recv_addr == RT_NULL))
514     {
515         while (length > 0)
516         {
517             send_addr += nu_spi_write(spi_base, send_addr, bytes_per_word);
518             length -= bytes_per_word;
519         }
520     } // if (send_addr != RT_NULL && recv_addr == RT_NULL)
521     // Read-only
522     else if ((send_addr == RT_NULL) && (recv_addr != RT_NULL))
523     {
524         spi_bus->dummy = 0;
525         while (length > 0)
526         {
527             /* Input data to SPI TX FIFO */
528             length -= nu_spi_write(spi_base, (const uint8_t *)&spi_bus->dummy, bytes_per_word);
529 
530             /* Read data from RX FIFO */
531             recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
532         }
533     } // else if (send_addr == RT_NULL && recv_addr != RT_NULL)
534     // Read&Write
535     else
536     {
537         while (length > 0)
538         {
539             /* Input data to SPI TX FIFO */
540             send_addr += nu_spi_write(spi_base, send_addr, bytes_per_word);
541             length -= bytes_per_word;
542 
543             /* Read data from RX FIFO */
544             recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
545         }
546     } // else
547 
548     /* Wait RX or drain RX-FIFO */
549     if (recv_addr)
550     {
551         // Wait SPI transmission done
552         while (SPI_IS_BUSY(spi_base))
553         {
554             while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
555             {
556                 recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
557             }
558         }
559 
560         while (!SPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
561         {
562             recv_addr += nu_spi_read(spi_base, recv_addr, bytes_per_word);
563         }
564     }
565     else
566     {
567         /* Clear SPI RX FIFO */
568         nu_spi_drain_rxfifo(spi_base);
569     }
570 }
571 
nu_spi_transfer(struct nu_spi * spi_bus,uint8_t * tx,uint8_t * rx,int length,uint8_t bytes_per_word)572 void nu_spi_transfer(struct nu_spi *spi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word)
573 {
574     RT_ASSERT(spi_bus != RT_NULL);
575 
576 #if defined(BSP_USING_SPI_PDMA)
577     /* DMA transfer constrains */
578     if ((spi_bus->pdma_chanid_rx >= 0) &&
579             !((uint32_t)tx % bytes_per_word) &&
580             !((uint32_t)rx % bytes_per_word) &&
581             (bytes_per_word != 3) &&
582             (length >= NU_SPI_USE_PDMA_MIN_THRESHOLD))
583         nu_spi_pdma_transmit(spi_bus, tx, rx, length, bytes_per_word);
584     else
585         nu_spi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word);
586 #else
587     nu_spi_transmission_with_poll(spi_bus, tx, rx, length, bytes_per_word);
588 #endif
589 }
590 
nu_spi_bus_xfer(struct rt_spi_device * device,struct rt_spi_message * message)591 static rt_ssize_t nu_spi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
592 {
593     struct nu_spi *spi_bus;
594     struct rt_spi_configuration *configuration;
595     uint8_t bytes_per_word;
596     void *pvUserData;
597 
598     RT_ASSERT(device != RT_NULL);
599     RT_ASSERT(device->bus != RT_NULL);
600     RT_ASSERT(message != RT_NULL);
601 
602     spi_bus = (struct nu_spi *) device->bus;
603     configuration = (struct rt_spi_configuration *)&spi_bus->configuration;
604     bytes_per_word = configuration->data_width / 8;
605     pvUserData = device->parent.user_data;
606 
607     if ((message->length % bytes_per_word) != 0)
608     {
609         /* Say bye. */
610         LOG_E("%s: error payload length(%d%%%d != 0).\n", spi_bus->name, message->length, bytes_per_word);
611         return 0;
612     }
613 
614     if (message->length > 0)
615     {
616         if (message->cs_take && !(configuration->mode & RT_SPI_NO_CS))
617         {
618             if (pvUserData != RT_NULL)
619             {
620                 if (configuration->mode & RT_SPI_CS_HIGH)
621                 {
622                     // set to HIGH */
623                     rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
624                 }
625                 else
626                 {
627                     // set to LOW */
628                     rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
629                 }
630             }
631             else
632             {
633                 if (configuration->mode & RT_SPI_CS_HIGH)
634                 {
635                     SPI_SET_SS_HIGH(spi_bus->spi_base);
636                 }
637                 else
638                 {
639                     SPI_SET_SS_LOW(spi_bus->spi_base);
640                 }
641             }
642         }
643 
644         nu_spi_transfer(spi_bus, (uint8_t *)message->send_buf, (uint8_t *)message->recv_buf, message->length, bytes_per_word);
645 
646         if (message->cs_release && !(configuration->mode & RT_SPI_NO_CS))
647         {
648             if (pvUserData != RT_NULL)
649             {
650                 if (configuration->mode & RT_SPI_CS_HIGH)
651                 {
652                     // set to LOW */
653                     rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
654                 }
655                 else
656                 {
657                     // set to HIGH */
658                     rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
659                 }
660             }
661             else
662             {
663                 if (configuration->mode & RT_SPI_CS_HIGH)
664                 {
665                     SPI_SET_SS_LOW(spi_bus->spi_base);
666                 }
667                 else
668                 {
669                     SPI_SET_SS_HIGH(spi_bus->spi_base);
670                 }
671             }
672         }
673 
674     }
675 
676     return message->length;
677 }
678 
nu_spi_register_bus(struct nu_spi * spi_bus,const char * name)679 static int nu_spi_register_bus(struct nu_spi *spi_bus, const char *name)
680 {
681     return rt_spi_bus_register(&spi_bus->dev, name, &nu_spi_poll_ops);
682 }
683 
684 /**
685  * Hardware SPI Initial
686  */
rt_hw_spi_init(void)687 static int rt_hw_spi_init(void)
688 {
689     int i;
690 
691     for (i = (SPI_START + 1); i < SPI_CNT; i++)
692     {
693         nu_spi_register_bus(&nu_spi_arr[i], nu_spi_arr[i].name);
694 #if defined(BSP_USING_SPI_PDMA)
695         nu_spi_arr[i].pdma_chanid_tx = -1;
696         nu_spi_arr[i].pdma_chanid_rx = -1;
697         if ((nu_spi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_spi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED))
698         {
699             if (nu_hw_spi_pdma_allocate(&nu_spi_arr[i]) != RT_EOK)
700             {
701                 LOG_W("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_spi_arr[i].name);
702             }
703         }
704 #endif
705     }
706 
707     return 0;
708 }
709 
710 INIT_DEVICE_EXPORT(rt_hw_spi_init);
711 
712 #endif //#if defined(BSP_USING_SPI)
713