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 * 2011-12-09 onelife Initial creation for EFM32
9 * 2011-12-27 onelife Utilize "LEUART_PRESENT" and "LEUART_COUNT"
10 */
11
12 /***************************************************************************//**
13 * @addtogroup efm32
14 * @{
15 ******************************************************************************/
16
17 /* Includes ------------------------------------------------------------------*/
18 #include "board.h"
19 #include "hdl_interrupt.h"
20 #include "drv_leuart.h"
21
22 #if (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1))
23 #if !defined(LEUART_PRESENT)
24 #error "LEUART module is not available"
25 #endif
26 /* Private typedef -----------------------------------------------------------*/
27 /* Private define ------------------------------------------------------------*/
28 /* Private macro -------------------------------------------------------------*/
29 #ifdef RT_LEUART_DEBUG
30 #define leuart_debug(format,args...) rt_kprintf(format, ##args)
31 #else
32 #define leuart_debug(format,args...)
33 #endif
34
35 /* Private variables ---------------------------------------------------------*/
36 #if defined(RT_USING_LEUART0)
37 #if (RT_USING_LEUART0 >= EFM32_LEUART_LOCATION_COUNT)
38 #error "Wrong location number"
39 #endif
40 struct rt_device leuart0_device;
41 static struct rt_semaphore leuart0_lock;
42 #endif
43
44 #if defined(RT_USING_LEUART1)
45 #if (LEUART_COUNT <= 1)
46 #error "Wrong unit number"
47 #endif
48 #if (RT_USING_LEUART1 >= EFM32_LEUART_LOCATION_COUNT)
49 #error "Wrong location number"
50 #endif
51 struct rt_device leuart1_device;
52 static struct rt_semaphore leuart1_lock;
53 #endif
54
55 /* Private function prototypes -----------------------------------------------*/
56 /* Private functions ---------------------------------------------------------*/
57 /***************************************************************************//**
58 * @brief
59 * Initialize LEUART device
60 *
61 * @details
62 *
63 * @note
64 *
65 * @param[in] dev
66 * Pointer to device descriptor
67 *
68 * @return
69 * Error code
70 ******************************************************************************/
rt_leuart_init(rt_device_t dev)71 static rt_err_t rt_leuart_init (rt_device_t dev)
72 {
73 struct efm32_leuart_device_t *leuart;
74
75 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
76
77 if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
78 {
79 if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
80 {
81 struct efm32_leuart_dma_mode_t *dma_tx;
82
83 dma_tx = (struct efm32_leuart_dma_mode_t *)(leuart->tx_mode);
84
85 leuart->state |= LEUART_STATE_RX_BUSY;
86 }
87
88 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
89 {
90 struct efm32_leuart_int_mode_t *int_rx;
91
92 int_rx = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
93
94 int_rx->data_ptr = RT_NULL;
95 }
96
97 /* Enable LEUART */
98 LEUART_Enable(leuart->leuart_device, leuartEnable);
99
100 dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
101 }
102
103 return RT_EOK;
104 }
105
106 /***************************************************************************//**
107 * @brief
108 * Open LEUART device
109 *
110 * @details
111 *
112 * @note
113 *
114 * @param[in] dev
115 * Pointer to device descriptor
116 *
117 * @param[in] oflag
118 * Device open flag
119 *
120 * @return
121 * Error code
122 ******************************************************************************/
rt_leuart_open(rt_device_t dev,rt_uint16_t oflag)123 static rt_err_t rt_leuart_open(rt_device_t dev, rt_uint16_t oflag)
124 {
125 RT_ASSERT(dev != RT_NULL);
126
127 struct efm32_leuart_device_t *leuart;
128
129 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
130
131 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
132 {
133 IRQn_Type rxIrq;
134
135 //if (leuart->state & LEUART_STATE_CONSOLE)
136 { /* Allocate new RX buffer */
137 struct efm32_leuart_int_mode_t *int_mode;
138
139 int_mode = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
140
141 if ((int_mode->data_ptr = rt_malloc(LEUART_RX_BUFFER_SIZE)) == RT_NULL)
142 {
143 leuart_debug("LEUART%d err: no mem for RX BUF\n", leuart->unit);
144 return -RT_ENOMEM;
145 }
146 rt_memset(int_mode->data_ptr, 0, LEUART_RX_BUFFER_SIZE);
147 int_mode->data_size = LEUART_RX_BUFFER_SIZE;
148 int_mode->read_index = 0;
149 int_mode->save_index = 0;
150 }
151
152 /* Enable RX interrupt */
153 leuart->leuart_device->IEN = LEUART_IEN_RXDATAV;
154
155 /* Enable IRQ */
156 switch (leuart->unit)
157 {
158 case 0:
159 rxIrq = LEUART0_IRQn;
160 break;
161 #if (LEUART_COUNT > 1)
162 case 1:
163 rxIrq = LEUART1_IRQn;
164 break;
165 #endif
166 }
167 if (oflag != RT_DEVICE_OFLAG_WRONLY)
168 {
169 NVIC_ClearPendingIRQ(rxIrq);
170 NVIC_SetPriority(rxIrq, EFM32_IRQ_PRI_DEFAULT);
171 NVIC_EnableIRQ(rxIrq);
172 }
173 }
174
175 /* Clear Flag */
176 leuart->leuart_device->IFC = _LEUART_IFC_MASK;
177
178 if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (oflag != RT_DEVICE_OFLAG_RDONLY))
179 {
180 /* DMA IRQ is enabled by DMA_Init() */
181 NVIC_SetPriority(DMA_IRQn, EFM32_IRQ_PRI_DEFAULT);
182 }
183
184 leuart->counter++;
185 leuart_debug("LEUART%d: Open with flag %x\n", leuart->unit, oflag);
186 return RT_EOK;
187 }
188
189 /***************************************************************************//**
190 * @brief
191 * Close LEUART device
192 *
193 * @details
194 *
195 * @note
196 *
197 * @param[in] dev
198 * Pointer to device descriptor
199 *
200 * @return
201 * Error code
202 ******************************************************************************/
rt_leuart_close(rt_device_t dev)203 static rt_err_t rt_leuart_close(rt_device_t dev)
204 {
205 RT_ASSERT(dev != RT_NULL);
206
207 struct efm32_leuart_device_t *leuart;
208
209 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
210
211 if (--leuart->counter == 0)
212 {
213 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
214 {
215 struct efm32_leuart_int_mode_t *int_rx;
216
217 int_rx = (struct efm32_leuart_int_mode_t *)leuart->rx_mode;
218
219 rt_free(int_rx->data_ptr);
220 int_rx->data_ptr = RT_NULL;
221 }
222 }
223
224 return RT_EOK;
225 }
226
227 /***************************************************************************//**
228 * @brief
229 * Read from LEUART device
230 *
231 * @details
232 *
233 * @note
234 *
235 * @param[in] dev
236 * Pointer to device descriptor
237 *
238 * @param[in] pos
239 * Offset
240 *
241 * @param[in] buffer
242 * Poniter to the buffer
243 *
244 * @param[in] size
245 * Buffer size in byte
246 *
247 * @return
248 * Number of read bytes
249 ******************************************************************************/
rt_leuart_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)250 static rt_ssize_t rt_leuart_read (
251 rt_device_t dev,
252 rt_off_t pos,
253 void *buffer,
254 rt_size_t size)
255 {
256 struct efm32_leuart_device_t *leuart;
257 rt_uint8_t *ptr;
258 rt_err_t err_code;
259 rt_size_t read_len;
260
261 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
262
263 /* Lock device */
264 if (rt_hw_interrupt_check())
265 {
266 err_code = rt_sem_take(leuart->lock, RT_WAITING_NO);
267 }
268 else
269 {
270 err_code = rt_sem_take(leuart->lock, RT_WAITING_FOREVER);
271 }
272 if (err_code != RT_EOK)
273 {
274 rt_set_errno(err_code);
275 return 0;
276 }
277
278 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
279 {
280 ptr = buffer;
281
282 /* interrupt mode Rx */
283 while (size)
284 {
285 rt_base_t level;
286 struct efm32_leuart_int_mode_t *int_rx;
287
288 int_rx = (struct efm32_leuart_int_mode_t *)\
289 (((struct efm32_leuart_device_t *)(dev->user_data))->rx_mode);
290
291 /* disable interrupt */
292 level = rt_hw_interrupt_disable();
293
294 if (int_rx->read_index != int_rx->save_index)
295 {
296 /* read a character */
297 *ptr++ = int_rx->data_ptr[int_rx->read_index];
298 size--;
299
300 /* move to next position */
301 int_rx->read_index ++;
302 if (int_rx->read_index >= LEUART_RX_BUFFER_SIZE)
303 {
304 int_rx->read_index = 0;
305 }
306 }
307 else
308 {
309 /* set error code */
310 err_code = -RT_EEMPTY;
311
312 /* enable interrupt */
313 rt_hw_interrupt_enable(level);
314 break;
315 }
316
317 /* enable interrupt */
318 rt_hw_interrupt_enable(level);
319 }
320
321 read_len = (rt_uint32_t)ptr - (rt_uint32_t)buffer;
322 }
323 else
324 {
325 LEUART_TypeDef *leuart_device;
326
327 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
328 leuart_device = ((struct efm32_leuart_device_t *)(dev->user_data))->leuart_device;
329 ptr = buffer;
330
331 /* polling mode */
332 while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
333 {
334 while (leuart_device->STATUS & LEUART_STATUS_RXDATAV)
335 {
336 *ptr = leuart_device->RXDATA & 0xff;
337 ptr ++;
338 }
339 }
340
341 read_len = size;
342 }
343
344 /* Unlock device */
345 rt_sem_release(leuart->lock);
346
347 /* set error code */
348 rt_set_errno(err_code);
349 return read_len;
350 }
351
352 /***************************************************************************//**
353 * @brief
354 * Write to LEUART device
355 *
356 * @details
357 *
358 * @note
359 *
360 * @param[in] dev
361 * Pointer to device descriptor
362 *
363 * @param[in] pos
364 * Offset
365 *
366 * @param[in] buffer
367 * Poniter to the buffer
368 *
369 * @param[in] size
370 * Buffer size in byte
371 *
372 * @return
373 * Number of written bytes
374 ******************************************************************************/
rt_leuart_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)375 static rt_ssize_t rt_leuart_write (
376 rt_device_t dev,
377 rt_off_t pos,
378 const void* buffer,
379 rt_size_t size)
380 {
381 rt_err_t err_code;
382 rt_size_t write_size;
383 struct efm32_leuart_device_t* leuart;
384
385 write_size = 0;
386 leuart = (struct efm32_leuart_device_t*)(dev->user_data);
387
388 /* Lock device */
389 if (rt_hw_interrupt_check())
390 {
391 err_code = rt_sem_take(leuart->lock, RT_WAITING_NO);
392 }
393 else
394 {
395 err_code = rt_sem_take(leuart->lock, RT_WAITING_FOREVER);
396 }
397 if (err_code != RT_EOK)
398 {
399 rt_set_errno(err_code);
400 return 0;
401 }
402
403 if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (size > 2))
404 { /* DMA mode Tx */
405 struct efm32_leuart_dma_mode_t *dma_tx;
406
407 if (dev->flag & RT_DEVICE_FLAG_STREAM)
408 {
409 if (*((rt_uint8_t *)buffer + size - 1) == '\n')
410 {
411 *((rt_uint8_t *)buffer + size - 1) = '\r';
412 *((rt_uint8_t *)buffer + size++) = '\n';
413 *((rt_uint8_t *)buffer + size) = 0;
414 }
415 }
416
417 dma_tx = (struct efm32_leuart_dma_mode_t *)(leuart->tx_mode);
418 dma_tx->data_ptr = (rt_uint32_t *)buffer;
419 dma_tx->data_size = size;
420
421 leuart->state |= LEUART_STATE_TX_BUSY;
422
423 DMA_ActivateBasic(
424 dma_tx->dma_channel,
425 true,
426 false,
427 (void *)&(leuart->leuart_device->TXDATA),
428 (void *)buffer,
429 (rt_uint32_t)(size - 1));
430
431 /* Wait, otherwise the TX buffer is overwrite */
432 // if (leuart->state & LEUART_STATE_CONSOLE)
433 // {
434 while(leuart->state & LEUART_STATE_TX_BUSY);
435 // }
436 // else
437 // {
438 // while(leuart->state & LEUART_STATE_TX_BUSY)
439 // {
440 // rt_thread_delay(LEUART_WAIT_TIME_TX);
441 // }
442 // }
443 // TODO: This function blocks the process
444 write_size = size;
445 }
446 else
447 { /* polling mode */
448 rt_uint8_t *ptr = (rt_uint8_t *)buffer;
449
450 if (dev->flag & RT_DEVICE_FLAG_STREAM)
451 {
452 /* stream mode */
453 while (size)
454 {
455 if (*ptr == '\n')
456 {
457 while (!(leuart->leuart_device->STATUS & LEUART_STATUS_TXBL));
458 leuart->leuart_device->TXDATA = '\r';
459 }
460
461 while (!(leuart->leuart_device->STATUS & LEUART_STATUS_TXBL));
462 leuart->leuart_device->TXDATA = (rt_uint32_t)*ptr;
463 ++ptr; --size;
464 }
465 }
466 else
467 {
468 /* write data directly */
469 while (size)
470 {
471 while (!(leuart->leuart_device->STATUS & LEUART_STATUS_TXBL));
472 leuart->leuart_device->TXDATA = (rt_uint32_t)*ptr;
473 ++ptr; --size;
474 }
475 }
476
477 write_size = (rt_size_t)ptr - (rt_size_t)buffer;
478 }
479
480 /* Unlock device */
481 rt_sem_release(leuart->lock);
482
483 /* set error code */
484 rt_set_errno(err_code);
485 return write_size;
486 }
487
488 /***************************************************************************//**
489 * @brief
490 * Configure LEUART device
491 *
492 * @details
493 *
494 * @note
495 *
496 * @param[in] dev
497 * Pointer to device descriptor
498 *
499 * @param[in] cmd
500 * IIC control command
501 *
502 * @param[in] args
503 * Arguments
504 *
505 * @return
506 * Error code
507 ******************************************************************************/
rt_leuart_control(rt_device_t dev,rt_uint8_t cmd,void * args)508 static rt_err_t rt_leuart_control (
509 rt_device_t dev,
510 rt_uint8_t cmd,
511 void *args)
512 {
513 RT_ASSERT(dev != RT_NULL);
514
515 rt_err_t err_code;
516 struct efm32_leuart_device_t *leuart;
517
518 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
519
520 /* Lock device */
521 if (rt_hw_interrupt_check())
522 {
523 err_code = rt_sem_take(leuart->lock, RT_WAITING_NO);
524 }
525 else
526 {
527 err_code = rt_sem_take(leuart->lock, RT_WAITING_FOREVER);
528 }
529 if (err_code != RT_EOK)
530 {
531 return err_code;
532 }
533
534 switch (cmd)
535 {
536 case RT_DEVICE_CTRL_SUSPEND:
537 /* Suspend device */
538 dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
539 LEUART_Enable(leuart->leuart_device, leuartDisable);
540 break;
541
542 case RT_DEVICE_CTRL_RESUME:
543 /* Resume device */
544 dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
545 LEUART_Enable(leuart->leuart_device, leuartEnable);
546 break;
547
548 case RT_DEVICE_CTRL_LEUART_RBUFFER:
549 /* Set RX buffer */
550 {
551 struct efm32_leuart_int_mode_t *int_rx;
552 rt_uint8_t size;
553
554 int_rx = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
555 size = (rt_uint8_t)((rt_uint32_t)args & 0xFFUL);
556
557 /* Free previous RX buffer */
558 if (int_rx->data_ptr != RT_NULL)
559 {
560 if (size == 0)
561 { /* Free RX buffer */
562 rt_free(int_rx->data_ptr);
563 int_rx->data_ptr = RT_NULL;
564 }
565 else if (size != int_rx->data_size)
566 {
567 /* Re-allocate RX buffer */
568 if ((int_rx->data_ptr = rt_realloc(int_rx->data_ptr, size)) \
569 == RT_NULL)
570 {
571 leuart_debug("LEUART%d err: no mem for RX BUF\n", leuart->unit);
572 err_code = -RT_ENOMEM;
573 break;
574 }
575 // TODO: Is the following line necessary?
576 //rt_memset(int_rx->data_ptr, 0, size);
577 }
578 }
579 else
580 {
581 /* Allocate new RX buffer */
582 if ((int_rx->data_ptr = rt_malloc(size)) == RT_NULL)
583 {
584 leuart_debug("LEUART%d err: no mem for RX BUF\n", leuart->unit);
585 err_code = -RT_ENOMEM;
586 break;
587 }
588 }
589 int_rx->data_size = size;
590 int_rx->read_index = 0;
591 int_rx->save_index = 0;
592 }
593 break;
594
595 }
596
597 /* Unlock device */
598 rt_sem_release(leuart->lock);
599
600 return err_code;
601 }
602
603 /***************************************************************************//**
604 * @brief
605 * LEUART RX data valid interrupt handler
606 *
607 * @details
608 *
609 * @note
610 *
611 * @param[in] dev
612 * Pointer to device descriptor
613 ******************************************************************************/
rt_hw_leuart_rx_isr(rt_device_t dev)614 void rt_hw_leuart_rx_isr(rt_device_t dev)
615 {
616 struct efm32_leuart_device_t *leuart;
617 struct efm32_leuart_int_mode_t *int_rx;
618 rt_uint32_t flag;
619
620 /* interrupt mode receive */
621 RT_ASSERT(dev->flag & RT_DEVICE_FLAG_INT_RX);
622
623 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
624 int_rx = (struct efm32_leuart_int_mode_t *)(leuart->rx_mode);
625
626 RT_ASSERT(int_rx->data_ptr != RT_NULL);
627
628 /* Set status */
629 leuart->state |= LEUART_STATE_RX_BUSY;
630
631 /* save into rx buffer */
632 while (leuart->leuart_device->STATUS & LEUART_STATUS_RXDATAV)
633 {
634 rt_base_t level;
635
636 /* disable interrupt */
637 level = rt_hw_interrupt_disable();
638
639 /* save character */
640 int_rx->data_ptr[int_rx->save_index] = \
641 (rt_uint8_t)(leuart->leuart_device->RXDATA & 0xFFUL);
642 int_rx->save_index ++;
643 if (int_rx->save_index >= LEUART_RX_BUFFER_SIZE)
644 int_rx->save_index = 0;
645
646 /* if the next position is read index, discard this 'read char' */
647 if (int_rx->save_index == int_rx->read_index)
648 {
649 int_rx->read_index ++;
650 if (int_rx->read_index >= LEUART_RX_BUFFER_SIZE)
651 {
652 int_rx->read_index = 0;
653 }
654 }
655
656 /* enable interrupt */
657 rt_hw_interrupt_enable(level);
658 }
659
660 /* invoke callback */
661 if (dev->rx_indicate != RT_NULL)
662 {
663 rt_size_t rx_length;
664
665 /* get rx length */
666 rx_length = int_rx->read_index > int_rx->save_index ?
667 LEUART_RX_BUFFER_SIZE - int_rx->read_index + int_rx->save_index : \
668 int_rx->save_index - int_rx->read_index;
669
670 dev->rx_indicate(dev, rx_length);
671 }
672 }
673
674 /***************************************************************************//**
675 * @brief
676 * DMA for LEUART TX interrupt handler
677 *
678 * @details
679 *
680 * @note
681 *
682 * @param[in] dev
683 * Pointer to device descriptor
684 ******************************************************************************/
rt_hw_leuart_dma_tx_isr(rt_device_t dev)685 void rt_hw_leuart_dma_tx_isr(rt_device_t dev)
686 {
687 /* DMA mode receive */
688 struct efm32_leuart_device_t *leuart;
689 struct efm32_leuart_dma_mode_t *dma_tx;
690
691 RT_ASSERT(dev->flag & RT_DEVICE_FLAG_DMA_TX);
692
693 leuart = (struct efm32_leuart_device_t *)(dev->user_data);
694 dma_tx = (struct efm32_leuart_dma_mode_t *)(leuart->tx_mode);
695
696 /* invoke call to notify tx complete */
697 if (dev->tx_complete != RT_NULL)
698 {
699 dev->tx_complete(dev, dma_tx->data_ptr);
700 }
701
702 /* Set status */
703 leuart->state &= ~(rt_uint32_t)LEUART_STATE_TX_BUSY;
704 }
705
706 /***************************************************************************//**
707 * @brief
708 * Register LEUART device
709 *
710 * @details
711 *
712 * @note
713 *
714 * @param[in] device
715 * Pointer to device descriptor
716 *
717 * @param[in] name
718 * Device name
719 *
720 * @param[in] flag
721 * Configuration flags
722 *
723 * @param[in] leuart
724 * Pointer to LEUART device descriptor
725 *
726 * @return
727 * Error code
728 ******************************************************************************/
rt_hw_leuart_register(rt_device_t device,const char * name,rt_uint32_t flag,struct efm32_leuart_device_t * leuart)729 rt_err_t rt_hw_leuart_register(
730 rt_device_t device,
731 const char *name,
732 rt_uint32_t flag,
733 struct efm32_leuart_device_t *leuart)
734 {
735 RT_ASSERT(device != RT_NULL);
736
737 if ((flag & RT_DEVICE_FLAG_DMA_RX) ||
738 (flag & RT_DEVICE_FLAG_INT_TX))
739 {
740 RT_ASSERT(0);
741 }
742
743 device->type = RT_Device_Class_Char;
744 device->rx_indicate = RT_NULL;
745 device->tx_complete = RT_NULL;
746 device->init = rt_leuart_init;
747 device->open = rt_leuart_open;
748 device->close = rt_leuart_close;
749 device->read = rt_leuart_read;
750 device->write = rt_leuart_write;
751 device->control = rt_leuart_control;
752 device->user_data = leuart;
753
754 /* register a character device */
755 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
756 }
757
758 /***************************************************************************//**
759 * @brief
760 * Initialize the specified LEUART unit
761 *
762 * @details
763 *
764 * @note
765 *
766 * @param[in] device
767 * Pointer to device descriptor
768 *
769 * @param[in] unitNumber
770 * Unit number
771 *
772 * @param[in] location
773 * Pin location number
774 *
775 * @param[in] flag
776 * Configuration flag
777 *
778 * @param[in] dmaChannel
779 * DMA channel number for TX
780 *
781 * @param[in] console
782 * Indicate if using as console
783 *
784 * @return
785 * Pointer to LEUART device
786 ******************************************************************************/
rt_hw_leuart_unit_init(rt_device_t device,rt_uint8_t unitNumber,rt_uint8_t location,rt_uint32_t flag,rt_uint32_t dmaChannel,rt_uint8_t config)787 static struct efm32_leuart_device_t *rt_hw_leuart_unit_init(
788 rt_device_t device,
789 rt_uint8_t unitNumber,
790 rt_uint8_t location,
791 rt_uint32_t flag,
792 rt_uint32_t dmaChannel,
793 rt_uint8_t config)
794 {
795 struct efm32_leuart_device_t *leuart;
796 struct efm32_leuart_dma_mode_t *dma_mode;
797 DMA_CB_TypeDef *callback;
798 CMU_Clock_TypeDef leuartClock;
799 rt_uint32_t txDmaSelect;
800 GPIO_Port_TypeDef port_tx, port_rx, port_clk, port_cs;
801 rt_uint32_t pin_tx, pin_rx, pin_clk, pin_cs;
802 LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
803 efm32_irq_hook_init_t hook;
804
805 do
806 {
807 /* Allocate device */
808 leuart = rt_malloc(sizeof(struct efm32_leuart_device_t));
809 if (leuart == RT_NULL)
810 {
811 leuart_debug("LEUART%d err: no mem\n", unitNumber);
812 break;
813 }
814 leuart->counter = 0;
815 leuart->unit = unitNumber;
816 leuart->state = config;
817 leuart->tx_mode = RT_NULL;
818 leuart->rx_mode = RT_NULL;
819
820 /* Allocate TX */
821 dma_mode = RT_NULL;
822 if (flag & RT_DEVICE_FLAG_DMA_TX)
823 {
824 leuart->tx_mode = dma_mode = rt_malloc(sizeof(struct efm32_leuart_dma_mode_t));
825 if (dma_mode == RT_NULL)
826 {
827 leuart_debug("LEUART%d err: no mem for DMA TX\n", unitNumber);
828 break;
829 }
830 dma_mode->dma_channel = dmaChannel;
831 }
832
833 /* Allocate RX */
834 if (flag & RT_DEVICE_FLAG_INT_RX)
835 {
836 leuart->rx_mode = rt_malloc(sizeof(struct efm32_leuart_int_mode_t));
837 if (leuart->rx_mode == RT_NULL)
838 {
839 leuart_debug("LEUART%d err: no mem for INT RX\n, unitNumber");
840 break;
841 }
842 }
843
844 /* Initialization */
845 if (unitNumber >= LEUART_COUNT)
846 {
847 break;
848 }
849 switch (unitNumber)
850 {
851 case 0:
852 leuart->leuart_device = LEUART0;
853 leuartClock = (CMU_Clock_TypeDef)cmuClock_LEUART0;
854 txDmaSelect = DMAREQ_LEUART0_TXBL;
855 port_tx = AF_LEUART0_TX_PORT(location);
856 pin_tx = AF_LEUART0_TX_PIN(location);
857 port_rx = AF_LEUART0_RX_PORT(location);
858 pin_rx = AF_LEUART0_RX_PIN(location);
859 break;
860 #if (LEUART_COUNT > 1)
861 case 1:
862 leuart->leuart_device = LEUART1;
863 leuartClock = (CMU_Clock_TypeDef)cmuClock_LEUART1;
864 txDmaSelect = DMAREQ_LEUART1_TXBL;
865 port_tx = AF_LEUART1_TX_PORT(location);
866 pin_tx = AF_LEUART1_TX_PIN(location);
867 port_rx = AF_LEUART1_RX_PORT(location);
868 pin_rx = AF_LEUART1_RX_PIN(location);
869 break;
870 #endif
871 default:
872 break;
873 }
874
875 /* Do not prescale clock */
876 CMU_ClockDivSet(leuartClock, cmuClkDiv_1);
877
878 /* Enable LEUART clock */
879 CMU_ClockEnable(leuartClock, true);
880
881 /* Config GPIO */
882 GPIO_PinModeSet(
883 port_tx,
884 pin_tx,
885 gpioModePushPull,
886 0);
887 GPIO_PinModeSet(
888 port_rx,
889 pin_rx,
890 gpioModeInputPull,
891 1);
892
893 /* Config interrupt and NVIC */
894 if (flag & RT_DEVICE_FLAG_INT_RX)
895 {
896 hook.type = efm32_irq_type_leuart;
897 hook.unit = unitNumber;
898 hook.cbFunc = rt_hw_leuart_rx_isr;
899 hook.userPtr = device;
900 efm32_irq_hook_register(&hook);
901 }
902
903 /* Config DMA */
904 if (flag & RT_DEVICE_FLAG_DMA_TX)
905 {
906 DMA_CfgChannel_TypeDef chnlCfg;
907 DMA_CfgDescr_TypeDef descrCfg;
908
909 hook.type = efm32_irq_type_dma;
910 hook.unit = dmaChannel;
911 hook.cbFunc = rt_hw_leuart_dma_tx_isr;
912 hook.userPtr = device;
913 efm32_irq_hook_register(&hook);
914
915 callback = (DMA_CB_TypeDef *)rt_malloc(sizeof(DMA_CB_TypeDef));
916 if (callback == RT_NULL)
917 {
918 leuart_debug("LEUART%d err: no mem for callback\n", unitNumber);
919 break;
920 }
921 callback->cbFunc = DMA_IRQHandler_All;
922 callback->userPtr = RT_NULL;
923 callback->primary = 0;
924
925 /* Setting up DMA channel */
926 chnlCfg.highPri = false; /* Can't use with peripherals */
927 chnlCfg.enableInt = true; /* Interrupt for callback function */
928 chnlCfg.select = txDmaSelect;
929 chnlCfg.cb = callback;
930 DMA_CfgChannel(dmaChannel, &chnlCfg);
931
932 /* Setting up DMA channel descriptor */
933 descrCfg.dstInc = dmaDataIncNone;
934 descrCfg.srcInc = dmaDataInc1;
935 descrCfg.size = dmaDataSize1;
936 descrCfg.arbRate = dmaArbitrate1;
937 descrCfg.hprot = 0;
938 DMA_CfgDescr(dmaChannel, true, &descrCfg);
939 }
940
941 /* Init specified LEUART unit */
942 LEUART_Init(leuart->leuart_device, &init);
943
944 /* Enable RX and TX pins and set location */
945 leuart->leuart_device->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | \
946 (location << _LEUART_ROUTE_LOCATION_SHIFT);
947
948 /* Clear RX/TX buffers */
949 leuart->leuart_device->CMD = LEUART_CMD_CLEARRX | LEUART_CMD_CLEARTX;
950
951 return leuart;
952 } while(0);
953
954 if (leuart->rx_mode)
955 {
956 rt_free(leuart->rx_mode);
957 }
958 if (leuart->tx_mode)
959 {
960 rt_free(leuart->tx_mode);
961 }
962 if (leuart)
963 {
964 rt_free(leuart);
965 }
966 if (callback)
967 {
968 rt_free(leuart);
969 }
970
971 leuart_debug("LEUART%d err: init failed!\n", unitNumber);
972 return RT_NULL;
973 }
974
975 /***************************************************************************//**
976 * @brief
977 * Initialize all LEUART module related hardware and register LEUART device to
978 * kernel
979 *
980 * @details
981 *
982 * @note
983 ******************************************************************************/
rt_hw_leuart_init(void)984 void rt_hw_leuart_init(void)
985 {
986 struct efm32_leuart_device_t *leuart;
987 rt_uint32_t flag;
988 rt_uint8_t config;
989
990 do
991 {
992 #ifdef RT_USING_LEUART0
993 config = 0;
994 flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
995
996 #if (RT_CONSOLE_DEVICE == EFM_LEUART0)
997 config |= LEUART_STATE_CONSOLE;
998 flag |= RT_DEVICE_FLAG_STREAM;
999 #endif
1000
1001 #ifdef RT_LEUART0_USING_DMA
1002 RT_ASSERT(RT_LEUART0_USING_DMA < DMA_CHAN_COUNT);
1003 flag |= RT_DEVICE_FLAG_DMA_TX;
1004 #else
1005 #define RT_LEUART0_USING_DMA EFM32_NO_DMA
1006 #endif
1007
1008 /* Initialize and Register leuart0 */
1009 if ((leuart = rt_hw_leuart_unit_init(
1010 &leuart0_device,
1011 0,
1012 RT_USING_LEUART0,
1013 flag,
1014 RT_LEUART0_USING_DMA,
1015 config)) != RT_NULL)
1016 {
1017 rt_hw_leuart_register(&leuart0_device, RT_LEUART0_NAME, flag, leuart);
1018 }
1019 else
1020 {
1021 break;
1022 }
1023 /* Initialize lock for leuart0 */
1024 leuart->lock = &leuart0_lock;
1025 if (rt_sem_init(leuart->lock, RT_LEUART0_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
1026 {
1027 break;
1028 }
1029 #endif
1030
1031 #if ((LEUART_COUNT > 1) && defined(RT_USING_LEUART1))
1032 config = 0;
1033 flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
1034
1035 #if (RT_CONSOLE_DEVICE == EFM_LEUART1)
1036 config |= LEUART_STATE_CONSOLE;
1037 flag |= RT_DEVICE_FLAG_STREAM;
1038 #endif
1039
1040 #ifdef RT_LEUART1_USING_DMA
1041 RT_ASSERT(RT_LEUART1_USING_DMA < DMA_CHAN_COUNT);
1042 flag |= RT_DEVICE_FLAG_DMA_TX;
1043 #else
1044 #define RT_LEUART1_USING_DMA EFM32_NO_DMA
1045 #endif
1046
1047 /* Initialize and Register leuart1 */
1048 if ((leuart = rt_hw_leuart_unit_init(
1049 &leuart1_device,
1050 1,
1051 RT_USING_LEUART1,
1052 flag,
1053 RT_LEUART1_USING_DMA,
1054 config)) != RT_NULL)
1055 {
1056 rt_hw_leuart_register(&leuart1_device, RT_LEUART1_NAME, flag, leuart);
1057 }
1058 else
1059 {
1060 break;
1061 }
1062 /* Initialize lock for leuart1 */
1063 leuart->lock = &leuart1_lock;
1064 if (rt_sem_init(leuart->lock, RT_LEUART1_NAME, 1, RT_IPC_FLAG_FIFO) != RT_EOK)
1065 {
1066 break;
1067 }
1068 #endif
1069
1070 leuart_debug("LEUART: H/W init OK!\n");
1071 return;
1072 } while (0);
1073
1074 rt_kprintf("LEUART: H/W init failed!\n");
1075 }
1076
1077 #endif /* (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1)) */
1078 /***************************************************************************//**
1079 * @}
1080 ******************************************************************************/
1081