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