EFR32 Blue Gecko 1 Software Documentation  efr32bg1-doc-5.1.2
uartdrv.c
Go to the documentation of this file.
1 /***************************************************************************/
15 #include <string.h>
16 
17 #include "uartdrv.h"
18 
19 #include "em_device.h"
20 #include "em_emu.h"
21 #include "em_gpio.h"
22 #include "em_core.h"
23 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
24 #include "gpiointerrupt.h"
25 #endif
26 
27 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE) && defined(_USART_ROUTEPEN_CTSPEN_MASK)
28 #define UART_HW_FLOW_CONTROL_SUPPORT
29 #endif
30 
32 
33 #if defined( DMA_PRESENT ) && ( DMA_COUNT == 1 )
34 #define UART_DMA_IRQ DMA_IRQn
35 #define UART_DMA_IRQHANDLER() DMA_IRQHandler()
36 #elif defined( LDMA_PRESENT ) && ( LDMA_COUNT == 1 )
37 #define UART_DMA_IRQ LDMA_IRQn
38 #define UART_DMA_IRQHANDLER() LDMA_IRQHandler()
39 #else
40 #error "No valid UARTDRV DMA engine defined."
41 #endif
42 
43 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
44 static bool uartdrvHandleIsInitialized = false;
45 static UARTDRV_Handle_t uartdrvHandle[EMDRV_UARTDRV_MAX_DRIVER_INSTANCES];
46 #endif
47 
48 static bool ReceiveDmaComplete(unsigned int channel,
49  unsigned int sequenceNo,
50  void *userParam);
51 static bool TransmitDmaComplete(unsigned int channel,
52  unsigned int sequenceNo,
53  void *userParam);
54 
55 /***************************************************************************/
58 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
59 static UARTDRV_Handle_t HwFcCtsIrqGetDrvHandle(uint32_t gpioPinNo)
60 {
61  uint32_t i;
62 
63  for (i = 0; i < EMDRV_UARTDRV_MAX_DRIVER_INSTANCES; i++)
64  {
65  if (uartdrvHandle[i]->ctsPin == gpioPinNo)
66  {
67  return uartdrvHandle[i];
68  }
69  }
70  return NULL;
71 }
72 
73 /***************************************************************************/
76 static UARTDRV_FlowControlState_t HwFcGetClearToSendPin(UARTDRV_Handle_t handle)
77 {
78  if (handle->fcType == uartdrvFlowControlHw)
79  {
80  return (UARTDRV_FlowControlState_t)GPIO_PinInGet(handle->ctsPort, handle->ctsPin);
81  }
82  else
83  {
84  return uartdrvFlowControlOn;
85  }
86 }
87 
88 /***************************************************************************/
91 static void HwFcManageClearToSend(uint8_t gpioPinNo)
92 {
93  UARTDRV_Handle_t handle = HwFcCtsIrqGetDrvHandle(gpioPinNo);
94 
95  if (handle && handle->fcType == uartdrvFlowControlHw)
96  {
97  // If not auto mode, just assign the CTS pin state to the self state
98  // If auto mode, also control UART TX enable
99  handle->fcSelfState = HwFcGetClearToSendPin(handle);
100  // Only manage DMA if not already paused by SW
101  if (handle->fcSelfCfg == uartdrvFlowControlAuto && (handle->txDmaPaused == 0))
102  {
103  bool active = false;
104  Ecode_t status = DMADRV_TransferActive( handle->txDmaCh , &active );
105  if ((handle->fcSelfState == uartdrvFlowControlOn) || handle->IgnoreRestrain)
106  {
107  handle->IgnoreRestrain = false;
108  DMADRV_ResumeTransfer(handle->txDmaCh);
109  }
110  // Only pause DMA if currently active
111  else if ((status == ECODE_EMDRV_DMADRV_OK) && active)
112  {
113  DMADRV_PauseTransfer(handle->txDmaCh);
114  }
115  }
116  }
117 }
118 
119 static Ecode_t FcApplyState(UARTDRV_Handle_t handle)
120 {
121  uint8_t fcSwCode;
122 
123  if (handle->fcType == uartdrvFlowControlHw)
124  {
125  if (handle->fcSelfCfg == uartdrvFlowControlOn)
126  {
127  // Assert nRTS (application control)
128  GPIO_PinOutClear(handle->rtsPort, handle->rtsPin);
129  }
130  else if (handle->fcSelfCfg == uartdrvFlowControlOff)
131  {
132  // Deassert nRTS (application control)
133  GPIO_PinOutSet(handle->rtsPort, handle->rtsPin);
134  }
135  else // Auto mode
136  {
137  if (handle->fcSelfState == uartdrvFlowControlOn)
138  {
139  // Assert nRTS
140  GPIO_PinOutClear(handle->rtsPort, handle->rtsPin);
141  }
142  else // Off
143  {
144  // Deassert nRTS
145  GPIO_PinOutSet(handle->rtsPort, handle->rtsPin);
146  }
147  }
148  }
149  else if (handle->fcType == uartdrvFlowControlSw)
150  {
151  if (handle->fcSelfState == uartdrvFlowControlOn)
152  {
153  fcSwCode = UARTDRV_FC_SW_XON;
154  // Pause transmit to ensure XON transmits immediately
155  UARTDRV_PauseTransmit(handle);
156  UARTDRV_ForceTransmit(handle, &fcSwCode, 1);
157  UARTDRV_ResumeTransmit(handle);
158  }
159  else
160  {
161  fcSwCode = UARTDRV_FC_SW_XOFF;
162  // Pause transmit to ensure XOFF transmits immediately
163  UARTDRV_PauseTransmit(handle);
164  UARTDRV_ForceTransmit(handle, &fcSwCode, 1);
165  UARTDRV_ResumeTransmit(handle);
166  }
167  }
168  return ECODE_EMDRV_UARTDRV_OK;
169 }
170 #else
171 // CTS pin should always read as uartdrvFlowControlOn when HW FC is disabled
172 #define HwFcGetClearToSendPin(x) uartdrvFlowControlOn
173 #endif /* EMDRV_UARTDRV_FLOW_CONTROL_ENABLE */
174 
175 /***************************************************************************/
178 static Ecode_t EnqueueBuffer(UARTDRV_Buffer_FifoQueue_t *queue,
179  UARTDRV_Buffer_t *inputBuffer,
180  UARTDRV_Buffer_t **queueBuffer)
181 {
183 
185  if (queue->used >= queue->size)
186  {
187  *queueBuffer = NULL;
190  }
191  memcpy((void *)&queue->fifo[queue->head],
192  (const void *)inputBuffer,
193  sizeof(UARTDRV_Buffer_t));
194  *queueBuffer = &queue->fifo[queue->head];
195  queue->head = (queue->head + 1) % queue->size;
196  queue->used++;
198 
199  return ECODE_EMDRV_UARTDRV_OK;
200 }
201 
202 /***************************************************************************/
205 static Ecode_t DequeueBuffer(UARTDRV_Buffer_FifoQueue_t *queue,
206  UARTDRV_Buffer_t **buffer)
207 {
209 
211  if (queue->used == 0)
212  {
213  *buffer = NULL;
216  }
217  *buffer = &queue->fifo[queue->tail];
218  queue->tail = (queue->tail + 1) % queue->size;
219  queue->used--;
221 
222  return ECODE_EMDRV_UARTDRV_OK;
223 }
224 
225 /***************************************************************************/
228 static Ecode_t GetTailBuffer(UARTDRV_Buffer_FifoQueue_t *queue,
229  UARTDRV_Buffer_t **buffer)
230 {
232 
234  if (queue->used == 0)
235  {
236  *buffer = NULL;
239  }
240  *buffer = &queue->fifo[queue->tail];
241 
243  return ECODE_EMDRV_UARTDRV_OK;
244 }
245 
246 /***************************************************************************/
249 static void EnableTransmitter(UARTDRV_Handle_t handle)
250 {
251  if (handle->type == uartdrvUartTypeUart)
252  {
253  // Enable TX
254  handle->peripheral.uart->CMD = USART_CMD_TXEN;
255  // Wait for TX to be enabled
256  while (!(handle->peripheral.uart->STATUS & USART_STATUS_TXENS));
257 
258  // Enable TX route
259 #if defined(USART_ROUTEPEN_TXPEN)
260  handle->peripheral.uart->ROUTEPEN |= USART_ROUTEPEN_TXPEN;
261 #else
262  handle->peripheral.uart->ROUTE |= USART_ROUTE_TXPEN;
263 #endif
264  }
265  else if (handle->type == uartdrvUartTypeLeuart)
266  {
267  // Wait for previous register writes to sync
268  while (handle->peripheral.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
269 
270  // Enable TX
271  handle->peripheral.leuart->CMD = LEUART_CMD_TXEN;
272  // Wait for TX to be enabled
273  while (!(handle->peripheral.leuart->STATUS & LEUART_STATUS_TXENS));
274 
275  // Enable TX route
276 #if defined(LEUART_ROUTEPEN_TXPEN)
277  handle->peripheral.leuart->ROUTEPEN |= LEUART_ROUTEPEN_TXPEN;
278 #else
279  handle->peripheral.leuart->ROUTE |= LEUART_ROUTE_TXPEN;
280 #endif
281  }
282 }
283 
284 /***************************************************************************/
287 static void DisableTransmitter(UARTDRV_Handle_t handle)
288 {
289  if (handle->type == uartdrvUartTypeUart)
290  {
291  // Disable TX route
292 #if defined(USART_ROUTEPEN_TXPEN)
293  handle->peripheral.uart->ROUTEPEN &= ~USART_ROUTEPEN_TXPEN;
294 #else
295  handle->peripheral.uart->ROUTE &= ~USART_ROUTE_TXPEN;
296 #endif
297  // Disable TX
298  handle->peripheral.uart->CMD = USART_CMD_TXDIS;
299  }
300  else if (handle->type == uartdrvUartTypeLeuart)
301  {
302  // Wait for previous register writes to sync
303  while (handle->peripheral.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
304 
305  // Disable TX route
306 #if defined(LEUART_ROUTEPEN_TXPEN)
307  handle->peripheral.leuart->ROUTEPEN &= ~LEUART_ROUTEPEN_TXPEN;
308 #else
309  handle->peripheral.leuart->ROUTE &= ~LEUART_ROUTE_TXPEN;
310 #endif
311  // Disable TX
312  handle->peripheral.leuart->CMD = LEUART_CMD_TXDIS;
313  }
314 }
315 
316 /***************************************************************************/
319 static void EnableReceiver(UARTDRV_Handle_t handle)
320 {
321  if (handle->type == uartdrvUartTypeUart)
322  {
323  // Enable RX
324  handle->peripheral.uart->CMD = USART_CMD_RXEN;
325  // Wait for RX to be enabled
326  while (!(handle->peripheral.uart->STATUS & USART_STATUS_RXENS));
327 
328  // Enable RX route
329 #if defined(USART_ROUTEPEN_RXPEN)
330  handle->peripheral.uart->ROUTEPEN |= USART_ROUTEPEN_RXPEN;
331 #else
332  handle->peripheral.uart->ROUTE |= USART_ROUTE_RXPEN;
333 #endif
334  }
335  else if (handle->type == uartdrvUartTypeLeuart)
336  {
337  // Wait for previous register writes to sync
338  while (handle->peripheral.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
339 
340  // Enable RX
341  handle->peripheral.leuart->CMD = LEUART_CMD_RXEN;
342  // Wait for RX to be enabled
343  while (!(handle->peripheral.leuart->STATUS & LEUART_STATUS_RXENS));
344 
345  // Enable RX route
346 #if defined(LEUART_ROUTEPEN_RXPEN)
347  handle->peripheral.leuart->ROUTEPEN |= LEUART_ROUTEPEN_RXPEN;
348 #else
349  handle->peripheral.leuart->ROUTE |= LEUART_ROUTE_RXPEN;
350 #endif
351  }
352 }
353 
354 /***************************************************************************/
357 static void DisableReceiver(UARTDRV_Handle_t handle)
358 {
359  if (handle->type == uartdrvUartTypeUart)
360  {
361  // Disable RX route
362 #if defined(USART_ROUTEPEN_RXPEN)
363  handle->peripheral.uart->ROUTEPEN &= ~USART_ROUTEPEN_RXPEN;
364 #else
365  handle->peripheral.uart->ROUTE &= ~USART_ROUTE_RXPEN;
366 #endif
367  // Disable RX
368  handle->peripheral.uart->CMD = USART_CMD_RXDIS;
369  }
370  else if (handle->type == uartdrvUartTypeLeuart)
371  {
372  // Wait for prevous register writes to sync
373  while (handle->peripheral.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
374 
375  // Disable RX route
376 #if defined(LEUART_ROUTEPEN_RXPEN)
377  handle->peripheral.leuart->ROUTEPEN &= ~LEUART_ROUTEPEN_RXPEN;
378 #else
379  handle->peripheral.leuart->ROUTE &= ~LEUART_ROUTE_RXPEN;
380 #endif
381  // Disable RX
382  handle->peripheral.leuart->CMD = LEUART_CMD_RXDIS;
383  }
384 }
385 
386 /***************************************************************************/
389 static void StartReceiveDma(UARTDRV_Handle_t handle,
390  UARTDRV_Buffer_t *buffer)
391 {
392  void *rxPort = NULL;
393 
394  handle->rxDmaActive = true;
395  if (handle->type == uartdrvUartTypeUart)
396  {
397  rxPort = (void *)&(handle->peripheral.uart->RXDATA);
398  }
399  else if (handle->type == uartdrvUartTypeLeuart)
400  {
401  rxPort = (void *)&(handle->peripheral.leuart->RXDATA);
402  }
403  else
404  {
405  handle->rxDmaActive = false;
406  return;
407  }
408 
409  DMADRV_PeripheralMemory(handle->rxDmaCh,
410  handle->rxDmaSignal,
411  buffer->data,
412  rxPort,
413  true,
414  buffer->transferCount,
416  ReceiveDmaComplete,
417  handle);
418 }
419 
420 /***************************************************************************/
423 static void StartTransmitDma(UARTDRV_Handle_t handle,
424  UARTDRV_Buffer_t *buffer)
425 {
426  void *txPort = NULL;
427 
428  handle->txDmaActive = true;
429  if (handle->type == uartdrvUartTypeUart)
430  {
431  txPort = (void *)&(handle->peripheral.uart->TXDATA);
432  }
433  else if (handle->type == uartdrvUartTypeLeuart)
434  {
435  txPort = (void *)&(handle->peripheral.leuart->TXDATA);
436  }
437  else
438  {
439  handle->txDmaActive = false;
440  return;
441  }
442 
443  DMADRV_MemoryPeripheral(handle->txDmaCh,
444  handle->txDmaSignal,
445  txPort,
446  buffer->data,
447  true,
448  buffer->transferCount,
450  TransmitDmaComplete,
451  handle);
452 }
453 
454 /***************************************************************************/
457 static bool ReceiveDmaComplete(unsigned int channel,
458  unsigned int sequenceNo,
459  void *userParam)
460 {
462  UARTDRV_Handle_t handle;
463  UARTDRV_Buffer_t *buffer;
464  (void)channel;
465  (void)sequenceNo;
466 
467  handle = (UARTDRV_Handle_t)userParam;
468  GetTailBuffer(handle->rxQueue, &buffer);
469 
470  if (handle->type == uartdrvUartTypeUart
471  && (handle->peripheral.uart->IF & USART_IF_FERR))
472  {
474  buffer->itemsRemaining = 0;
475  handle->peripheral.uart->IFC = USART_IFC_FERR;
476  }
477  else if (handle->type == uartdrvUartTypeLeuart
478  && (handle->peripheral.leuart->IF & LEUART_IF_FERR))
479  {
481  buffer->itemsRemaining = 0;
482  handle->peripheral.leuart->IFC = LEUART_IFC_FERR;
483  }
484  else if (handle->type == uartdrvUartTypeUart
485  && (handle->peripheral.uart->IF & USART_IF_PERR))
486  {
488  buffer->itemsRemaining = 0;
489  handle->peripheral.uart->IFC = USART_IFC_PERR;
490  }
491  else if (handle->type == uartdrvUartTypeLeuart
492  && (handle->peripheral.leuart->IF & LEUART_IF_PERR))
493  {
495  buffer->itemsRemaining = 0;
496  handle->peripheral.leuart->IFC = LEUART_IFC_PERR;
497  }
498  else
499  {
501  buffer->itemsRemaining = 0;
502  }
503 
505 
506  if (buffer->callback != NULL)
507  {
508  buffer->callback(handle, buffer->transferStatus, buffer->data, buffer->transferCount - buffer->itemsRemaining);
509  }
510  // Dequeue the current tail RX operation, check if more in queue
511  DequeueBuffer(handle->rxQueue, &buffer);
512 
513  if (handle->rxQueue->used > 0)
514  {
515  GetTailBuffer(handle->rxQueue, &buffer);
516  StartReceiveDma(handle, buffer);
517  }
518  else
519  {
520 #if EMDRV_UARTDRV_FLOW_CONTROL_ENABLE
521  handle->fcSelfState = uartdrvFlowControlOff;
522  FcApplyState(handle);
523 #endif
524  handle->rxDmaActive = false;
525 
526  if (handle->fcType != uartdrvFlowControlHwUart)
527  {
528  DisableReceiver(handle);
529  }
530  }
532  return true;
533 }
534 
535 
536 /***************************************************************************/
539 static bool TransmitDmaComplete(unsigned int channel,
540  unsigned int sequenceNo,
541  void *userParam)
542 {
544  UARTDRV_Handle_t handle;
545  UARTDRV_Buffer_t *buffer;
546  (void)channel;
547  (void)sequenceNo;
548 
549  handle = (UARTDRV_Handle_t)userParam;
550  GetTailBuffer(handle->txQueue, &buffer);
551 
552  EFM_ASSERT(buffer != NULL);
553 
555  buffer->itemsRemaining = 0;
556 
558 
559  if (buffer->callback != NULL)
560  {
561  buffer->callback(handle, ECODE_EMDRV_UARTDRV_OK, buffer->data, buffer->transferCount);
562  }
563  // Dequeue the current tail TX operation, check if more in queue
564  DequeueBuffer(handle->txQueue, &buffer);
565 
566  if (handle->txQueue->used > 0)
567  {
568  GetTailBuffer(handle->txQueue, &buffer);
569  StartTransmitDma(handle, buffer);
570  }
571  else
572  {
573  handle->txDmaActive = false;
574  }
576  return true;
577 }
578 
579 
580 /***************************************************************************/
583 static Ecode_t CheckParams(UARTDRV_Handle_t handle, void *data, uint32_t count)
584 {
585  if (handle == NULL)
586  {
588  }
589  if ((data == NULL) || (count == 0) || (count > DMADRV_MAX_XFER_COUNT))
590  {
592  }
593  return ECODE_EMDRV_UARTDRV_OK;
594 }
595 
596 /***************************************************************************/
599 static Ecode_t SetupGpioUart(UARTDRV_Handle_t handle,
600  const UARTDRV_InitUart_t * initData)
601 {
602 #if defined(_USART_ROUTELOC0_MASK)
603  if (false)
604  {
605 #if defined(USARTRF0)
606  }
607  else if (handle->peripheral.uart == USARTRF0)
608  {
609  handle->txPort = (GPIO_Port_TypeDef)AF_USARTRF0_TX_PORT(initData->portLocationTx);
610  handle->rxPort = (GPIO_Port_TypeDef)AF_USARTRF0_RX_PORT(initData->portLocationRx);
611  handle->txPin = AF_USARTRF0_TX_PIN(initData->portLocationTx);
612  handle->rxPin = AF_USARTRF0_RX_PIN(initData->portLocationRx);
613 #endif
614 #if defined(USARTRF1)
615  }
616  else if (handle->peripheral.uart == USARTRF1)
617  {
618  handle->txPort = (GPIO_Port_TypeDef)AF_USARTRF1_TX_PORT(initData->portLocationTx);
619  handle->rxPort = (GPIO_Port_TypeDef)AF_USARTRF1_RX_PORT(initData->portLocationRx);
620  handle->txPin = AF_USARTRF1_TX_PIN(initData->portLocationTx);
621  handle->rxPin = AF_USARTRF1_RX_PIN(initData->portLocationRx);
622 #endif
623 #if defined(USART0)
624  }
625  else if (handle->peripheral.uart == USART0)
626  {
627  handle->txPort = (GPIO_Port_TypeDef)AF_USART0_TX_PORT(initData->portLocationTx);
628  handle->rxPort = (GPIO_Port_TypeDef)AF_USART0_RX_PORT(initData->portLocationRx);
629  handle->txPin = AF_USART0_TX_PIN(initData->portLocationTx);
630  handle->rxPin = AF_USART0_RX_PIN(initData->portLocationRx);
631 #endif
632 #if defined(USART1)
633  }
634  else if (handle->peripheral.uart == USART1)
635  {
636  handle->txPort = (GPIO_Port_TypeDef)AF_USART1_TX_PORT(initData->portLocationTx);
637  handle->rxPort = (GPIO_Port_TypeDef)AF_USART1_RX_PORT(initData->portLocationRx);
638  handle->txPin = AF_USART1_TX_PIN(initData->portLocationTx);
639  handle->rxPin = AF_USART1_RX_PIN(initData->portLocationRx);
640 #endif
641 #if defined(USART2)
642  }
643  else if (handle->peripheral.uart == USART2)
644  {
645  handle->txPort = (GPIO_Port_TypeDef)AF_USART2_TX_PORT(initData->portLocationTx);
646  handle->rxPort = (GPIO_Port_TypeDef)AF_USART2_RX_PORT(initData->portLocationRx);
647  handle->txPin = AF_USART2_TX_PIN(initData->portLocationTx);
648  handle->rxPin = AF_USART2_RX_PIN(initData->portLocationRx);
649 #endif
650 #if defined(USART3)
651  }
652  else if (handle->peripheral.uart == USART3)
653  {
654  handle->txPort = (GPIO_Port_TypeDef)AF_USART3_TX_PORT(initData->portLocationTx);
655  handle->rxPort = (GPIO_Port_TypeDef)AF_USART3_RX_PORT(initData->portLocationRx);
656  handle->txPin = AF_USART3_TX_PIN(initData->portLocationTx);
657  handle->rxPin = AF_USART3_RX_PIN(initData->portLocationRx);
658 #endif
659 #if defined(USART4)
660  }
661  else if (handle->peripheral.uart == USART4)
662  {
663  handle->txPort = (GPIO_Port_TypeDef)AF_USART4_TX_PORT(initData->portLocationTx);
664  handle->rxPort = (GPIO_Port_TypeDef)AF_USART4_RX_PORT(initData->portLocationRx);
665  handle->txPin = AF_USART4_TX_PIN(initData->portLocationTx);
666  handle->rxPin = AF_USART4_RX_PIN(initData->portLocationRx);
667 #endif
668 #if defined(USART5)
669  }
670  else if (handle->peripheral.uart == USART5)
671  {
672  handle->txPort = (GPIO_Port_TypeDef)AF_USART5_TX_PORT(initData->portLocationTx);
673  handle->rxPort = (GPIO_Port_TypeDef)AF_USART5_RX_PORT(initData->portLocationRx);
674  handle->txPin = AF_USART5_TX_PIN(initData->portLocationTx);
675  handle->rxPin = AF_USART5_RX_PIN(initData->portLocationRx);
676 #endif
677 #if defined(UART0)
678  }
679  else if (handle->peripheral.uart == UART0)
680  {
681  handle->txPort = (GPIO_Port_TypeDef)AF_UART0_TX_PORT(initData->portLocationTx);
682  handle->rxPort = (GPIO_Port_TypeDef)AF_UART0_RX_PORT(initData->portLocationRx);
683  handle->txPin = AF_UART0_TX_PIN(initData->portLocationTx);
684  handle->rxPin = AF_UART0_RX_PIN(initData->portLocationRx);
685 #endif
686 #if defined(UART1)
687  }
688  else if (handle->peripheral.uart == UART1)
689  {
690  handle->txPort = (GPIO_Port_TypeDef)AF_UART1_TX_PORT(initData->portLocationTx);
691  handle->rxPort = (GPIO_Port_TypeDef)AF_UART1_RX_PORT(initData->portLocationRx);
692  handle->txPin = AF_UART1_TX_PIN(initData->portLocationTx);
693  handle->rxPin = AF_UART1_RX_PIN(initData->portLocationRx);
694 #endif
695 #if defined(UART2)
696  }
697  else if (handle->peripheral.uart == UART2)
698  {
699  handle->txPort = (GPIO_Port_TypeDef)AF_UART2_TX_PORT(initData->portLocationTx);
700  handle->rxPort = (GPIO_Port_TypeDef)AF_UART2_RX_PORT(initData->portLocationRx);
701  handle->txPin = AF_UART2_TX_PIN(initData->portLocationTx);
702  handle->rxPin = AF_UART2_RX_PIN(initData->portLocationRx);
703 #endif
704  }
705  else
706  {
708  }
709 #else
710  if (false)
711  {
712 #if defined(USARTRF0)
713  }
714  else if (handle->peripheral.uart == USARTRF0)
715  {
716  handle->txPort = (GPIO_Port_TypeDef)AF_USARTRF0_TX_PORT(initData->portLocation);
717  handle->rxPort = (GPIO_Port_TypeDef)AF_USARTRF0_RX_PORT(initData->portLocation);
718  handle->txPin = AF_USARTRF0_TX_PIN(initData->portLocation);
719  handle->rxPin = AF_USARTRF0_RX_PIN(initData->portLocation);
720 #endif
721 #if defined(USARTRF1)
722  }
723  else if (handle->peripheral.uart == USARTRF1)
724  {
725  handle->txPort = (GPIO_Port_TypeDef)AF_USARTRF1_TX_PORT(initData->portLocation);
726  handle->rxPort = (GPIO_Port_TypeDef)AF_USARTRF1_RX_PORT(initData->portLocation);
727  handle->txPin = AF_USARTRF1_TX_PIN(initData->portLocation);
728  handle->rxPin = AF_USARTRF1_RX_PIN(initData->portLocation);
729 #endif
730 #if defined(USART0)
731  }
732  else if (handle->peripheral.uart == USART0)
733  {
734  handle->txPort = (GPIO_Port_TypeDef)AF_USART0_TX_PORT(initData->portLocation);
735  handle->rxPort = (GPIO_Port_TypeDef)AF_USART0_RX_PORT(initData->portLocation);
736  handle->txPin = AF_USART0_TX_PIN(initData->portLocation);
737  handle->rxPin = AF_USART0_RX_PIN(initData->portLocation);
738 #endif
739 #if defined(USART1)
740  }
741  else if (handle->peripheral.uart == USART1)
742  {
743  handle->txPort = (GPIO_Port_TypeDef)AF_USART1_TX_PORT(initData->portLocation);
744  handle->rxPort = (GPIO_Port_TypeDef)AF_USART1_RX_PORT(initData->portLocation);
745  handle->txPin = AF_USART1_TX_PIN(initData->portLocation);
746  handle->rxPin = AF_USART1_RX_PIN(initData->portLocation);
747 #endif
748 #if defined(USART2)
749  }
750  else if (handle->peripheral.uart == USART2)
751  {
752  handle->txPort = (GPIO_Port_TypeDef)AF_USART2_TX_PORT(initData->portLocation);
753  handle->rxPort = (GPIO_Port_TypeDef)AF_USART2_RX_PORT(initData->portLocation);
754  handle->txPin = AF_USART2_TX_PIN(initData->portLocation);
755  handle->rxPin = AF_USART2_RX_PIN(initData->portLocation);
756 #endif
757 #if defined(UART0)
758  }
759  else if (handle->peripheral.uart == UART0)
760  {
761  handle->txPort = (GPIO_Port_TypeDef)AF_UART0_TX_PORT(initData->portLocation);
762  handle->rxPort = (GPIO_Port_TypeDef)AF_UART0_RX_PORT(initData->portLocation);
763  handle->txPin = AF_UART0_TX_PIN(initData->portLocation);
764  handle->rxPin = AF_UART0_RX_PIN(initData->portLocation);
765 #endif
766 #if defined(UART1)
767  }
768  else if (handle->peripheral.uart == UART1)
769  {
770  handle->txPort = (GPIO_Port_TypeDef)AF_UART1_TX_PORT(initData->portLocation);
771  handle->rxPort = (GPIO_Port_TypeDef)AF_UART1_RX_PORT(initData->portLocation);
772  handle->txPin = AF_UART1_TX_PIN(initData->portLocation);
773  handle->rxPin = AF_UART1_RX_PIN(initData->portLocation);
774 #endif
775  }
776  else
777  {
779  }
780 #endif
781 
782  handle->ctsPort = initData->ctsPort;
783  handle->ctsPin = initData->ctsPin;
784  handle->rtsPort = initData->rtsPort;
785  handle->rtsPin = initData->rtsPin;
786 
787  return ECODE_EMDRV_UARTDRV_OK;
788 }
789 
790 /***************************************************************************/
793 static Ecode_t SetupGpioLeuart(UARTDRV_Handle_t handle,
794  const UARTDRV_InitLeuart_t * initData)
795 {
796 #if defined(_LEUART_ROUTELOC0_MASK)
797  if (false)
798  {
799 #if defined(LEUART0)
800  }
801  else if (handle->peripheral.leuart == LEUART0)
802  {
803  handle->txPort = (GPIO_Port_TypeDef)AF_LEUART0_TX_PORT(initData->portLocationTx);
804  handle->rxPort = (GPIO_Port_TypeDef)AF_LEUART0_RX_PORT(initData->portLocationRx);
805  handle->txPin = AF_LEUART0_TX_PIN(initData->portLocationTx);
806  handle->rxPin = AF_LEUART0_RX_PIN(initData->portLocationRx);
807 #endif
808 #if defined(LEUART1)
809  }
810  else if (handle->peripheral.leuart == LEUART1)
811  {
812  handle->txPort = (GPIO_Port_TypeDef)AF_LEUART1_TX_PORT(initData->portLocationTx);
813  handle->rxPort = (GPIO_Port_TypeDef)AF_LEUART1_RX_PORT(initData->portLocationRx);
814  handle->txPin = AF_LEUART1_TX_PIN(initData->portLocationTx);
815  handle->rxPin = AF_LEUART1_RX_PIN(initData->portLocationRx);
816 #endif
817  }
818  else
819  {
821  }
822 #else
823  if (false)
824  {
825 #if defined(LEUART0)
826  }
827  else if (handle->peripheral.leuart == LEUART0)
828  {
829  handle->txPort = (GPIO_Port_TypeDef)AF_LEUART0_TX_PORT(initData->portLocation);
830  handle->rxPort = (GPIO_Port_TypeDef)AF_LEUART0_RX_PORT(initData->portLocation);
831  handle->txPin = AF_LEUART0_TX_PIN(initData->portLocation);
832  handle->rxPin = AF_LEUART0_RX_PIN(initData->portLocation);
833 #endif
834 #if defined(LEUART1)
835  }
836  else if (handle->peripheral.leuart == LEUART1)
837  {
838  handle->txPort = (GPIO_Port_TypeDef)AF_LEUART1_TX_PORT(initData->portLocation);
839  handle->rxPort = (GPIO_Port_TypeDef)AF_LEUART1_RX_PORT(initData->portLocation);
840  handle->txPin = AF_LEUART1_TX_PIN(initData->portLocation);
841  handle->rxPin = AF_LEUART1_RX_PIN(initData->portLocation);
842 #endif
843  }
844  else
845  {
847  }
848 #endif
849 
850  handle->ctsPort = initData->ctsPort;
851  handle->ctsPin = initData->ctsPin;
852  handle->rtsPort = initData->rtsPort;
853  handle->rtsPin = initData->rtsPin;
854 
855  return ECODE_EMDRV_UARTDRV_OK;
856 }
857 
858 /***************************************************************************/
861 static Ecode_t ConfigGpio(UARTDRV_Handle_t handle, bool enable)
862 {
863  if (enable)
864  {
865  GPIO_PinModeSet(handle->txPort, handle->txPin, gpioModePushPull, 1);
866  GPIO_PinModeSet(handle->rxPort, handle->rxPin, gpioModeInputPull, 1);
867 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
868  if (handle->fcType == uartdrvFlowControlHw)
869  {
870  GPIO_PinModeSet(handle->ctsPort, handle->ctsPin, gpioModeInput, 0);
871  GPIO_PinModeSet(handle->rtsPort, handle->rtsPin, gpioModePushPull, 0);
872  GPIO_IntConfig(handle->ctsPort, handle->ctsPin, true, true, true);
873  }
874  else if (handle->fcType == uartdrvFlowControlHwUart)
875  {
876  GPIO_PinModeSet(handle->ctsPort, handle->ctsPin, gpioModeInput, 0);
877  GPIO_PinModeSet(handle->rtsPort, handle->rtsPin, gpioModePushPull, 0);
878  }
879 #endif
880  }
881  else
882  {
883  GPIO_PinModeSet(handle->txPort, handle->txPin, gpioModeDisabled, 0);
884  GPIO_PinModeSet(handle->rxPort, handle->rxPin, gpioModeDisabled, 0);
885 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
886  if (handle->fcType == uartdrvFlowControlHw)
887  {
888  GPIO_PinModeSet(handle->ctsPort, handle->ctsPin, gpioModeDisabled, 0);
889  GPIO_PinModeSet(handle->rtsPort, handle->rtsPin, gpioModeDisabled, 0);
890  GPIO_IntConfig(handle->ctsPort, handle->ctsPin, true, true, false);
891  }
892  else if (handle->fcType == uartdrvFlowControlHwUart)
893  {
894  GPIO_PinModeSet(handle->ctsPort, handle->ctsPin, gpioModeDisabled, 0);
895  GPIO_PinModeSet(handle->rtsPort, handle->rtsPin, gpioModeDisabled, 0);
896  }
897 #endif
898  }
899  return ECODE_EMDRV_UARTDRV_OK;
900 }
901 
902 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
903 /***************************************************************************/
906 static Ecode_t SetHandleIndex(UARTDRV_Handle_t handle)
907 {
908  bool handleIsSet;
909  uint32_t handleIdx;
910 
911  // Set handler pointer in handler array
912  if (!uartdrvHandleIsInitialized)
913  {
914  for (handleIdx = 0; handleIdx < EMDRV_UARTDRV_MAX_DRIVER_INSTANCES; handleIdx++)
915  {
916  uartdrvHandle[handleIdx] = NULL;
917  }
918  uartdrvHandleIsInitialized = true;
919  }
920 
921  handleIsSet = false;
922  for (handleIdx = 0; handleIdx < EMDRV_UARTDRV_MAX_DRIVER_INSTANCES; handleIdx++)
923  {
924  if ((uartdrvHandle[handleIdx] == NULL) || (uartdrvHandle[handleIdx] == handle))
925  {
926  uartdrvHandle[handleIdx] = handle;
927  handleIsSet = true;
928  break;
929  }
930  }
931 
932  if (!handleIsSet)
933  {
935  }
936 
937  return ECODE_EMDRV_UARTDRV_OK;
938 }
939 #endif
940 
941 /***************************************************************************/
944 static void InitializeQueues(UARTDRV_Handle_t handle,
945  UARTDRV_Buffer_FifoQueue_t * rxQueue,
946  UARTDRV_Buffer_FifoQueue_t * txQueue)
947 {
948  handle->rxQueue = rxQueue;
949  handle->rxQueue->head = 0;
950  handle->rxQueue->tail = 0;
951  handle->rxQueue->used = 0;
952  handle->rxDmaActive = false;
953 
954  handle->txQueue = txQueue;
955  handle->txQueue->head = 0;
956  handle->txQueue->tail = 0;
957  handle->txQueue->used = 0;
958  handle->txDmaActive = false;
959 
960  handle->IgnoreRestrain = false;
961 }
962 
963 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
964 /***************************************************************************/
967 static void InitializeGpioFlowControl(UARTDRV_Handle_t handle)
968 {
969  GPIOINT_Init();
970  GPIOINT_CallbackRegister(handle->ctsPin, HwFcManageClearToSend);
971  handle->fcPeerState = uartdrvFlowControlOn;
972  handle->fcSelfState = uartdrvFlowControlOn;
973  handle->fcSelfCfg = uartdrvFlowControlAuto;
974  FcApplyState(handle);
975 }
976 #endif
977 
978 /***************************************************************************/
981 static Ecode_t InitializeDma(UARTDRV_Handle_t handle)
982 {
983  // Initialize DMA.
984  DMADRV_Init();
985 
986  if (DMADRV_AllocateChannel(&handle->txDmaCh, NULL) != ECODE_EMDRV_DMADRV_OK)
987  {
989  }
990 
991  if (DMADRV_AllocateChannel(&handle->rxDmaCh, NULL) != ECODE_EMDRV_DMADRV_OK)
992  {
994  }
995 
996  return ECODE_EMDRV_UARTDRV_OK;
997 }
999 
1000 
1001 /***************************************************************************/
1016  const UARTDRV_InitUart_t *initData)
1017 {
1018  Ecode_t retVal;
1021 
1022  if (handle == NULL)
1023  {
1025  }
1026  if (initData == NULL)
1027  {
1029  }
1030 
1031  memset(handle, 0, sizeof(UARTDRV_HandleData_t));
1032 
1033 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
1034  retVal = SetHandleIndex(handle);
1035  if (retVal != ECODE_EMDRV_UARTDRV_OK)
1036  {
1037  return retVal;
1038  }
1039  handle->fcType = initData->fcType;
1040 #else
1041  // Force init data to uartdrvFlowControlNone if flow control is excluded by EMDRV_UARTDRV_FLOW_CONTROL_ENABLE
1042  handle->fcType = uartdrvFlowControlNone;
1043 #endif
1044 
1045  handle->peripheral.uart = initData->port;
1046  handle->type = uartdrvUartTypeUart;
1047 
1048  // Set clocks and DMA requests according to available peripherals
1049  if (false)
1050  {
1051 #if defined(USART0)
1052  }
1053  else if (initData->port == USART0)
1054  {
1055  handle->uartClock = cmuClock_USART0;
1056  handle->txDmaSignal = dmadrvPeripheralSignal_USART0_TXBL;
1057  handle->rxDmaSignal = dmadrvPeripheralSignal_USART0_RXDATAV;
1058 #endif
1059 #if defined(USART1)
1060  }
1061  else if (initData->port == USART1)
1062  {
1063  handle->uartClock = cmuClock_USART1;
1064  handle->txDmaSignal = dmadrvPeripheralSignal_USART1_TXBL;
1065  handle->rxDmaSignal = dmadrvPeripheralSignal_USART1_RXDATAV;
1066 #endif
1067 #if defined(USART2)
1068  }
1069  else if (initData->port == USART2)
1070  {
1071  handle->uartClock = cmuClock_USART2;
1072  handle->txDmaSignal = dmadrvPeripheralSignal_USART2_TXBL;
1073  handle->rxDmaSignal = dmadrvPeripheralSignal_USART2_RXDATAV;
1074 #endif
1075 #if defined(USART3)
1076  }
1077  else if (initData->port == USART3)
1078  {
1079  handle->uartClock = cmuClock_USART3;
1080  handle->txDmaSignal = dmadrvPeripheralSignal_USART3_TXBL;
1081  handle->rxDmaSignal = dmadrvPeripheralSignal_USART3_RXDATAV;
1082 #endif
1083 #if defined(USART4)
1084  }
1085  else if (initData->port == USART4)
1086  {
1087  handle->uartClock = cmuClock_USART4;
1088  handle->txDmaSignal = dmadrvPeripheralSignal_USART4_TXBL;
1089  handle->rxDmaSignal = dmadrvPeripheralSignal_USART4_RXDATAV;
1090 #endif
1091 #if defined(USART5)
1092  }
1093  else if (initData->port == USART5)
1094  {
1095  handle->uartClock = cmuClock_USART5;
1096  handle->txDmaSignal = dmadrvPeripheralSignal_USART5_TXBL;
1097  handle->rxDmaSignal = dmadrvPeripheralSignal_USART5_RXDATAV;
1098 #endif
1099 #if defined(UART0)
1100  }
1101  else if (initData->port == UART0)
1102  {
1103  handle->uartClock = cmuClock_UART0;
1104  handle->txDmaSignal = dmadrvPeripheralSignal_UART0_TXBL;
1105  handle->rxDmaSignal = dmadrvPeripheralSignal_UART0_RXDATAV;
1106 #endif
1107 #if defined(UART1)
1108  }
1109  else if (initData->port == UART1)
1110  {
1111  handle->uartClock = cmuClock_UART1;
1112  handle->txDmaSignal = dmadrvPeripheralSignal_UART1_TXBL;
1113  handle->rxDmaSignal = dmadrvPeripheralSignal_UART1_RXDATAV;
1114 #endif
1115 #if defined(UART2)
1116  }
1117  else if (initData->port == UART2)
1118  {
1119  handle->uartClock = cmuClock_UART2;
1120  handle->txDmaSignal = dmadrvPeripheralSignal_UART2_TXBL;
1121  handle->rxDmaSignal = dmadrvPeripheralSignal_UART2_RXDATAV;
1122 #endif
1123  }
1124  else
1125  {
1127  }
1128 
1129  InitializeQueues(handle, initData->rxQueue, initData->txQueue);
1130 
1131  usartInit.baudrate = initData->baudRate;
1132  usartInit.stopbits = initData->stopBits;
1133  usartInit.parity = initData->parity;
1134  usartInit.oversampling = initData->oversampling;
1135 #if defined(USART_CTRL_MVDIS)
1136  usartInit.mvdis = initData->mvdis;
1137 #endif
1138 
1139  // UARTDRV is fixed at 8 bit frames.
1141 
1142  // Enable clocks
1145  CMU_ClockEnable(handle->uartClock, true);
1146 
1147  // Init U(S)ART to default async config.
1148  // RX/TX enable is done on demand
1149  usartInit.enable = usartDisable;
1150  USART_InitAsync(initData->port, &usartInit);
1151 
1152 #if defined(USART_ROUTEPEN_TXPEN)
1153  initData->port->ROUTEPEN = USART_ROUTEPEN_TXPEN
1155  initData->port->ROUTELOC0 = (initData->port->ROUTELOC0
1158  | (initData->portLocationTx
1160  | (initData->portLocationRx
1162 #else
1163  initData->port->ROUTE = USART_ROUTE_TXPEN
1164  | USART_ROUTE_RXPEN
1165  | (initData->portLocation
1166  << _USART_ROUTE_LOCATION_SHIFT);
1167 #endif
1168 
1169  if ((retVal = SetupGpioUart(handle, initData)) != ECODE_EMDRV_UARTDRV_OK)
1170  {
1171  return retVal;
1172  }
1173  if ((retVal = ConfigGpio(handle, true)) != ECODE_EMDRV_UARTDRV_OK)
1174  {
1175  return retVal;
1176  }
1177 
1179 
1180  // Configure hardware flow control pins and interrupt vectors
1181 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
1182  if (initData->fcType == uartdrvFlowControlHwUart)
1183  {
1184 #if defined(UART_HW_FLOW_CONTROL_SUPPORT)
1186  initData->port->CTRLX |= USART_CTRLX_CTSEN;
1187  initData->port->ROUTELOC1 = (initData->portLocationCts << _USART_ROUTELOC1_CTSLOC_SHIFT)
1189 #else
1190  // Attempting to use USART hardware flow control on a device that does not
1191  // support it.
1193 #endif
1194  }
1195  else if (initData->fcType == uartdrvFlowControlHw)
1196  {
1197  InitializeGpioFlowControl(handle);
1198  }
1199 #endif
1200 
1201  // Clear any false IRQ/DMA request
1202  USART_IntClear(initData->port, ~0x0);
1203 
1204  // Enable TX permanently as the TX circuit consumes very little energy.
1205  // RX is enabled on demand as the RX circuit consumes some energy due to
1206  // continuous (over)sampling.
1207  if (initData->fcType == uartdrvFlowControlHwUart)
1208  {
1209  // RX must be enabled permanently when using USART hw flow control
1210  USART_Enable(initData->port, usartEnable);
1211  }
1212  else
1213  {
1214  USART_Enable(initData->port, usartEnableTx);
1215  }
1216 
1217  // Discard false frames and/or IRQs
1219 
1220  // Initialize DMA.
1221  DMADRV_Init();
1222 
1223  retVal = InitializeDma(handle);
1224 
1225  CORE_EXIT_ATOMIC();
1226 
1227  if (retVal != ECODE_EMDRV_UARTDRV_OK)
1228  {
1229  return retVal;
1230  }
1231 
1232  return ECODE_EMDRV_UARTDRV_OK;
1233 }
1234 
1235 /***************************************************************************/
1250  const UARTDRV_InitLeuart_t *initData)
1251 {
1252  Ecode_t retVal;
1255 
1256 
1257  if (handle == NULL)
1258  {
1260  }
1261  if (initData == NULL)
1262  {
1264  }
1265  if (initData->fcType == uartdrvFlowControlHwUart)
1266  {
1267  // LEUART doesn't support peripheral hw flow control
1269  }
1270 
1271  memset(handle, 0, sizeof(UARTDRV_HandleData_t));
1272 
1273 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
1274  retVal = SetHandleIndex(handle);
1275  if (retVal != ECODE_EMDRV_UARTDRV_OK)
1276  {
1277  return retVal;
1278  }
1279  handle->fcType = initData->fcType;
1280 #else
1281  // Force init data to uartdrvFlowControlNone if flow control is excluded by EMDRV_UARTDRV_FLOW_CONTROL_ENABLE
1282  handle->fcType = uartdrvFlowControlNone;
1283 #endif
1284 
1285  handle->peripheral.leuart = initData->port;
1286  handle->type = uartdrvUartTypeLeuart;
1287 
1288  // Set clocks and DMA requests according to available peripherals
1289  if (false)
1290  {
1291 #if defined(LEUART0)
1292  }
1293  else if (initData->port == LEUART0)
1294  {
1295  handle->uartClock = cmuClock_LEUART0;
1296  handle->txDmaSignal = dmadrvPeripheralSignal_LEUART0_TXBL;
1297  handle->rxDmaSignal = dmadrvPeripheralSignal_LEUART0_RXDATAV;
1298 #endif
1299 #if defined(LEUART1)
1300  }
1301  else if (initData->port == LEUART1)
1302  {
1303  handle->uartClock = cmuClock_LEUART1;
1304  handle->txDmaSignal = dmadrvPeripheralSignal_LEUART1_TXBL;
1305  handle->rxDmaSignal = dmadrvPeripheralSignal_LEUART1_RXDATAV;
1306 #endif
1307  }
1308  else
1309  {
1311  }
1312 
1313  InitializeQueues(handle, initData->rxQueue, initData->txQueue);
1314 
1315  leuartInit.baudrate = initData->baudRate;
1316  leuartInit.stopbits = initData->stopBits;
1317  leuartInit.parity = initData->parity;
1318 
1319  // UARTDRV is fixed at 8 bit frames.
1321 
1322  // Enable clocks
1326 
1327  // Only try to use LF clock if LFXO is enabled and requested baudrate is low
1328  if (CMU->STATUS & CMU_STATUS_LFXOENS
1329  && (leuartInit.baudrate <= SystemLFXOClockGet()))
1330  {
1332  }
1333  else
1334  {
1335  // Try to figure out the prescaler that will give us the best stability
1337 
1338 #if defined( _SILICON_LABS_32B_SERIES_0 )
1339  // Attainable baudrate lies between refclk and refclk/128. For maximum
1340  // accuracy, we want the reference clock to be as high as possible.
1341  uint32_t refclk = CMU_ClockFreqGet(cmuClock_LFB);
1342  uint8_t divisor = 0;
1343 
1344  while (leuartInit.baudrate <= (refclk >> (divisor + 7)))
1345  {
1346  divisor++;
1347  }
1348 
1349  // If we ran out of stretch on the clock division, error out.
1351  {
1353  }
1354  CMU_ClockDivSet(handle->uartClock, (CMU_ClkDiv_TypeDef) (1 << divisor));
1355 #elif defined( _SILICON_LABS_32B_SERIES_1 )
1356  // Clock divider in LEUARTn is large enough for any baudrate.
1357 #endif
1358  }
1359 
1360 
1361  CMU_ClockEnable(handle->uartClock, true);
1362 
1363  // Init LEUART to default async config.
1364  // RX/TX enable is done on demand
1365  leuartInit.enable = leuartDisable;
1366  LEUART_Init(initData->port, &leuartInit);
1367 
1368 #if defined(LEUART_ROUTEPEN_TXPEN)
1369  initData->port->ROUTEPEN = LEUART_ROUTEPEN_TXPEN
1371  initData->port->ROUTELOC0 = (initData->port->ROUTELOC0
1374  | (initData->portLocationTx
1376  | (initData->portLocationRx
1378 #else
1379  initData->port->ROUTE = LEUART_ROUTE_TXPEN
1380  | LEUART_ROUTE_RXPEN
1381  | (initData->portLocation
1382  << _LEUART_ROUTE_LOCATION_SHIFT);
1383 #endif
1384 
1385  if ((retVal = SetupGpioLeuart(handle, initData)) != ECODE_EMDRV_UARTDRV_OK)
1386  {
1387  return retVal;
1388  }
1389  if ((retVal = ConfigGpio(handle, true)) != ECODE_EMDRV_UARTDRV_OK)
1390  {
1391  return retVal;
1392  }
1393 
1395 
1396  // Configure hardware flow control pins and interrupt vectors
1397 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
1398  if (initData->fcType == uartdrvFlowControlHw)
1399  {
1400  InitializeGpioFlowControl(handle);
1401  }
1402 #endif
1403 
1404  // Clear any false IRQ/DMA request
1405  LEUART_IntClear(initData->port, ~0x0);
1406 
1407  // Enable TX permanently as the TX circuit consumes very little energy.
1408  // RX is enabled on demand as the RX circuit consumes some energy due to
1409  // continuous (over)sampling.
1410  LEUART_Enable(initData->port, leuartEnableTx);
1411 
1412  // Wait for previous write (TXEN) to sync before clearing FIFOs
1413  while (initData->port->SYNCBUSY & LEUART_SYNCBUSY_CMD);
1414 
1415  // Discard false frames and/or IRQs
1417 
1418  // Initialize DMA.
1419  DMADRV_Init();
1420 
1421  retVal = InitializeDma(handle);
1422 
1423  CORE_EXIT_ATOMIC();
1424 
1425  if (retVal != ECODE_EMDRV_UARTDRV_OK)
1426  {
1427  return retVal;
1428  }
1429 
1430  // Wait for everything to be synchronized
1431  while (initData->port->SYNCBUSY);
1432  return ECODE_EMDRV_UARTDRV_OK;
1433 }
1434 
1435 
1436 /***************************************************************************/
1447 {
1448  if (handle == NULL)
1449  {
1451  }
1452  // Stop DMA transfers.
1453  UARTDRV_Abort(handle, uartdrvAbortAll);
1454 
1455  // Do not leave any peer restrained on DeInit
1457 
1458  ConfigGpio(handle, false);
1459  if (handle->type == uartdrvUartTypeUart)
1460  {
1461  handle->peripheral.uart->CMD = USART_CMD_RXDIS;
1462  handle->peripheral.uart->CMD = USART_CMD_TXDIS;
1463  }
1464  else if (handle->type == uartdrvUartTypeLeuart)
1465  {
1466  LEUART_Reset(handle->peripheral.leuart);
1467  while (handle->peripheral.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
1468  handle->peripheral.leuart->CMD = LEUART_CMD_RXDIS | LEUART_CMD_TXDIS;
1469  }
1470 
1471  CMU_ClockEnable(handle->uartClock, false);
1472 
1473 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
1474  if (handle->fcType != uartdrvFlowControlHwUart)
1475  {
1476  GPIOINT_CallbackRegister(handle->ctsPin, NULL);
1477  }
1478 #endif
1479 
1480  DMADRV_FreeChannel(handle->txDmaCh);
1481  DMADRV_FreeChannel(handle->rxDmaCh);
1482  DMADRV_DeInit();
1483 
1484  handle->rxQueue->head = 0;
1485  handle->rxQueue->tail = 0;
1486  handle->rxQueue->used = 0;
1487 
1488  handle->txQueue->head = 0;
1489  handle->txQueue->tail = 0;
1490  handle->txQueue->used = 0;
1491 
1492  return ECODE_EMDRV_UARTDRV_OK;
1493 }
1494 
1495 
1496 /***************************************************************************/
1512 {
1513  UARTDRV_Buffer_t *rxBuffer, *txBuffer;
1515 
1516  if (handle == NULL) {
1518  }
1519 
1521  if ((type == uartdrvAbortTransmit) && (handle->txQueue->used == 0))
1522  {
1523  CORE_EXIT_ATOMIC();
1524  return ECODE_EMDRV_UARTDRV_IDLE;
1525  }
1526  else if ((type == uartdrvAbortReceive) && (handle->rxQueue->used == 0))
1527  {
1528  CORE_EXIT_ATOMIC();
1529  return ECODE_EMDRV_UARTDRV_IDLE;
1530  }
1531  else if ((type == uartdrvAbortAll)
1532  && (handle->txQueue->used == 0)
1533  && (handle->rxQueue->used == 0))
1534  {
1535  CORE_EXIT_ATOMIC();
1536  return ECODE_EMDRV_UARTDRV_IDLE;
1537  }
1538 
1539  // Stop DMA transfers.
1540  if ((type == uartdrvAbortTransmit) || (type == uartdrvAbortAll))
1541  {
1542  // Stop the current transfer
1543  DMADRV_StopTransfer(handle->txDmaCh);
1544  handle->txDmaActive = false;
1545 
1546  if (handle->txQueue->used > 0)
1547  {
1548  // Update the transfer status of the active transfer
1549  GetTailBuffer(handle->txQueue, &txBuffer);
1550  DMADRV_TransferRemainingCount(handle->txDmaCh,
1551  (int*)&txBuffer->itemsRemaining);
1553 
1554  // Dequeue all transfers and call callback
1555  while (handle->txQueue->used > 0)
1556  {
1557  DequeueBuffer(handle->txQueue, &txBuffer);
1558 
1559  // Call the callback with ABORTED error code
1560  if (txBuffer->callback != NULL)
1561  {
1562  txBuffer->callback(handle,
1564  NULL,
1565  txBuffer->itemsRemaining);
1566  }
1567  }
1568  }
1569 
1570  // Wait for peripheral to finish cleaning up, to prevent framing errors
1571  // on subsequent transfers
1573  }
1574  if ((type == uartdrvAbortReceive) || (type == uartdrvAbortAll))
1575  {
1576  // Stop the current transfer
1577  DMADRV_StopTransfer(handle->rxDmaCh);
1578  handle->rxDmaActive = false;
1579 
1580  if (handle->rxQueue->used > 0)
1581  {
1582  // Update the transfer status of the active transfer
1583  GetTailBuffer(handle->rxQueue, &rxBuffer);
1584  DMADRV_TransferRemainingCount(handle->rxDmaCh,
1585  (int*)&rxBuffer->itemsRemaining);
1587 
1588  // Dequeue all transfers and call callback
1589  while (handle->rxQueue->used > 0)
1590  {
1591  DequeueBuffer(handle->rxQueue, &rxBuffer);
1592 
1593  // Call the callback with ABORTED error code
1594  if (rxBuffer->callback != NULL)
1595  {
1596  rxBuffer->callback(handle,
1598  NULL,
1599  rxBuffer->itemsRemaining);
1600  }
1601  }
1602  }
1603 
1604  // Disable the receiver
1605  if (handle->fcType != uartdrvFlowControlHwUart)
1606  {
1607  DisableReceiver(handle);
1608  }
1609  }
1610  CORE_EXIT_ATOMIC();
1611 
1612  return ECODE_EMDRV_UARTDRV_OK;
1613 }
1614 
1615 /***************************************************************************/
1625 {
1626  UARTDRV_Status_t status = 0;
1627 
1628  if (handle->type == uartdrvUartTypeUart)
1629  {
1630  status = handle->peripheral.uart->STATUS;
1631  }
1632  else if (handle->type == uartdrvUartTypeLeuart)
1633  {
1634  uint32_t reg = handle->peripheral.leuart->STATUS;
1635  if (reg & LEUART_STATUS_TXENS)
1636  {
1637  status |= UARTDRV_STATUS_TXEN;
1638  }
1639  if (reg & LEUART_STATUS_RXENS)
1640  {
1641  status |= UARTDRV_STATUS_RXEN;
1642  }
1643  if (reg & LEUART_STATUS_RXBLOCK)
1644  {
1645  status |= UARTDRV_STATUS_RXBLOCK;
1646  }
1647  if (reg & LEUART_STATUS_TXC)
1648  {
1649  status |= UARTDRV_STATUS_TXC;
1650  }
1651  if (reg & LEUART_STATUS_TXBL)
1652  {
1653  status |= UARTDRV_STATUS_TXBL;
1654  }
1655  if (reg & LEUART_STATUS_RXDATAV)
1656  {
1657  status |= UARTDRV_STATUS_RXDATAV;
1658  }
1659 #if defined(LEUART_STATUS_TXIDLE)
1660  if (reg & LEUART_STATUS_TXIDLE)
1661  {
1662  status |= UARTDRV_STATUS_TXIDLE;
1663  }
1664 #endif
1665  }
1666 
1667 #if defined(_SILICON_LABS_32B_SERIES_0)
1668  // Series 0 devices does not have the TXIDLE flag, so we emulate it
1669  if ((status & UARTDRV_STATUS_TXC) || !(handle->hasTransmitted))
1670  {
1671  status |= UARTDRV_STATUS_TXIDLE;
1672  }
1673 #endif
1674 
1675  return status;
1676 }
1677 
1678 /***************************************************************************/
1688 {
1689  return (uint8_t)handle->rxQueue->used;
1690 }
1691 
1692 
1693 /***************************************************************************/
1710  uint8_t **buffer,
1711  UARTDRV_Count_t *itemsReceived,
1712  UARTDRV_Count_t *itemsRemaining)
1713 {
1714  UARTDRV_Buffer_t *rxBuffer = NULL;
1716  uint32_t remaining = 0;
1717 
1718  if (handle->rxQueue->used > 0)
1719  {
1720  retVal = GetTailBuffer(handle->rxQueue, &rxBuffer);
1721  DMADRV_TransferRemainingCount(handle->rxDmaCh,
1722  (int*)&remaining);
1723  }
1724 
1725  if (rxBuffer && (retVal == ECODE_EMDRV_UARTDRV_OK))
1726  {
1727  *itemsReceived = rxBuffer->transferCount - remaining;
1728  *itemsRemaining = remaining;
1729  *buffer = rxBuffer->data;
1730  }
1731  else
1732  {
1733  *itemsRemaining = 0;
1734  *itemsReceived = 0;
1735  *buffer = NULL;
1736  }
1737 
1738  return UARTDRV_GetPeripheralStatus(handle);
1739 }
1740 
1741 
1742 /***************************************************************************/
1752 {
1753  return (uint8_t)handle->txQueue->used;
1754 }
1755 
1756 /***************************************************************************/
1773  uint8_t **buffer,
1774  UARTDRV_Count_t *itemsSent,
1775  UARTDRV_Count_t *itemsRemaining)
1776 {
1777  UARTDRV_Buffer_t *txBuffer = NULL;
1779  uint32_t remaining = 0;
1780 
1781  if (handle->txQueue->used > 0)
1782  {
1783  retVal = GetTailBuffer(handle->txQueue, &txBuffer);
1784  DMADRV_TransferRemainingCount(handle->txDmaCh,
1785  (int*)&remaining);
1786  }
1787 
1788  if (txBuffer && (retVal == ECODE_EMDRV_UARTDRV_OK))
1789  {
1790  *itemsSent = txBuffer->transferCount - remaining;
1791  *itemsRemaining = remaining;
1792  *buffer = txBuffer->data;
1793  }
1794  else
1795  {
1796  *itemsRemaining = 0;
1797  *itemsSent = 0;
1798  *buffer = NULL;
1799  }
1800 
1801  return UARTDRV_GetPeripheralStatus(handle);
1802 }
1803 
1804 /***************************************************************************/
1817 {
1818 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
1819  if (handle->fcType == uartdrvFlowControlHwUart)
1820  {
1822  }
1823  handle->fcSelfCfg = state;
1824  if (state != uartdrvFlowControlAuto)
1825  {
1826  handle->fcSelfState = state;
1827  }
1828  return FcApplyState(handle);
1829 #else
1830  return ECODE_EMDRV_UARTDRV_OK;
1831 #endif
1832 }
1833 
1834 /***************************************************************************/
1847 {
1848  if ( (handle->fcType != uartdrvFlowControlSw) ||
1849  (state == uartdrvFlowControlAuto) )
1850  {
1852  }
1853 
1854  if (handle->fcPeerState != state)
1855  {
1856  handle->fcPeerState = state;
1857  if (state == uartdrvFlowControlOn)
1858  {
1859  UARTDRV_ResumeTransmit(handle);
1860  }
1861  else if (state == uartdrvFlowControlOff)
1862  {
1863  UARTDRV_PauseTransmit(handle);
1864  }
1865  }
1866 
1867  return ECODE_EMDRV_UARTDRV_OK;
1868 }
1869 
1870 /***************************************************************************/
1880 {
1881  return handle->fcPeerState;
1882 }
1883 
1884 
1885 /***************************************************************************/
1895 {
1896  return handle->fcSelfState;
1897 }
1898 
1899 
1900 /***************************************************************************/
1910 {
1911  handle->IgnoreRestrain = true;
1912 
1913  return ECODE_EMDRV_UARTDRV_OK;
1914 }
1915 
1916 
1917 /***************************************************************************/
1931  uint8_t *data,
1932  UARTDRV_Count_t maxCount)
1933 {
1934  Ecode_t retVal;
1935  uint32_t rxState;
1936  UARTDRV_Count_t i = 0;
1937 
1938  retVal = CheckParams(handle, data, maxCount);
1939  if (retVal != ECODE_EMDRV_UARTDRV_OK)
1940  {
1941  return 0;
1942  }
1943 
1944  // Wait for DMA receive to complete and clear
1945  while (handle->rxQueue->used > 0);
1946 
1947  if (handle->type == uartdrvUartTypeUart)
1948  {
1949  rxState = (handle->peripheral.uart->STATUS & USART_STATUS_RXENS);
1950  }
1951  else if (handle->type == uartdrvUartTypeLeuart)
1952  {
1953  rxState = (handle->peripheral.leuart->STATUS & LEUART_STATUS_RXENS);
1954  }
1955  else
1956  {
1957  EFM_ASSERT(false);
1958  rxState = 0;
1959  }
1960  if (!rxState)
1961  {
1962  EnableReceiver(handle);
1963  }
1964 
1965  if (handle->type == uartdrvUartTypeUart)
1966  {
1967  while ((handle->peripheral.uart->STATUS & USART_STATUS_RXDATAV))
1968  {
1969  *data = (uint8_t)handle->peripheral.uart->RXDATA;
1970  data++;
1971  i++;
1972  if (i >= maxCount)
1973  {
1974  break;
1975  }
1976  }
1977  }
1978  else if (handle->type == uartdrvUartTypeLeuart)
1979  {
1980  while ((handle->peripheral.leuart->STATUS & LEUART_STATUS_RXDATAV))
1981  {
1982  *data = (uint8_t)handle->peripheral.leuart->RXDATA;
1983  data++;
1984  i++;
1985  if (i >= maxCount)
1986  {
1987  break;
1988  }
1989  }
1990  }
1991  data -= i;
1992 
1993  if (!rxState)
1994  {
1995  DisableReceiver(handle);
1996  }
1997  return i;
1998 }
1999 
2000 
2001 /***************************************************************************/
2016  uint8_t *data,
2017  UARTDRV_Count_t count)
2018 {
2019  Ecode_t retVal;
2020  uint32_t txState;
2021  bool callDmaIrqHandler;
2022 
2023  retVal = CheckParams(handle, data, count);
2024  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2025  {
2026  return retVal;
2027  }
2028 
2029  // Wait for DMA transmit to complete and clear
2030  callDmaIrqHandler = CORE_IrqIsBlocked(UART_DMA_IRQ); // Loop invariant
2031  while((handle->txQueue->used > 0) && (!handle->txDmaPaused))
2032  {
2033  if (callDmaIrqHandler)
2034  {
2035  UART_DMA_IRQHANDLER();
2036  }
2037  }
2038 
2039  if (handle->type == uartdrvUartTypeUart)
2040  {
2041  txState = (handle->peripheral.uart->STATUS & USART_STATUS_TXENS);
2042  }
2043  else if (handle->type == uartdrvUartTypeLeuart)
2044  {
2045  txState = (handle->peripheral.leuart->STATUS & LEUART_STATUS_TXENS);
2046  }
2047  else
2048  {
2049  EFM_ASSERT(false);
2050  txState = 0;
2051  }
2052  if (!txState)
2053  {
2054  EnableTransmitter(handle);
2055  }
2056 
2057  handle->hasTransmitted = true;
2058 
2059  if (handle->type == uartdrvUartTypeUart)
2060  {
2061  while (count--)
2062  {
2063  USART_Tx(handle->peripheral.uart, *data++);
2064  }
2065  // Wait for TX completion
2066  while (!(handle->peripheral.uart->STATUS & USART_STATUS_TXC))
2067  {
2068  }
2069  }
2070  else if (handle->type == uartdrvUartTypeLeuart)
2071  {
2072  while (count--)
2073  {
2074  LEUART_Tx(handle->peripheral.leuart, *data++);
2075  }
2076  // Wait for TX completion
2077  while (!(handle->peripheral.leuart->STATUS & LEUART_STATUS_TXC));
2078  }
2079 
2080  if (!txState)
2081  {
2082  DisableTransmitter(handle);
2083  }
2084 
2085  return ECODE_EMDRV_UARTDRV_OK;
2086 }
2087 
2088 /***************************************************************************/
2099 {
2100  if (handle == NULL)
2101  {
2103  }
2104  bool active = false;
2105  // An active DMA transfer signifies that the channel is in use
2106  Ecode_t status = DMADRV_TransferActive( handle->txDmaCh , &active );
2107  if ( (status == ECODE_EMDRV_DMADRV_OK) && active )
2108  {
2109  // Pause the transfer if 1) pause counter is 0
2110  // 2) HW flow control hasn't already paused the DMA
2111  if ( (handle->txDmaPaused == 0) && (HwFcGetClearToSendPin(handle) == uartdrvFlowControlOn) )
2112  {
2113  DMADRV_PauseTransfer(handle->txDmaCh);
2114  }
2115  // Increment counter to allow nested calls
2116  handle->txDmaPaused++;
2117  }
2118  else
2119  {
2121  }
2122  return ECODE_EMDRV_UARTDRV_OK;
2123 }
2124 
2125 
2126 /***************************************************************************/
2142  uint8_t *data,
2143  UARTDRV_Count_t count,
2144  UARTDRV_Callback_t callback)
2145 {
2146  Ecode_t retVal;
2147  UARTDRV_Buffer_t outputBuffer;
2148  UARTDRV_Buffer_t *queueBuffer;
2149 
2150  retVal = CheckParams(handle, data, count);
2151  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2152  {
2153  return retVal;
2154  }
2155  outputBuffer.data = data;
2156  outputBuffer.transferCount = count;
2157  outputBuffer.itemsRemaining = count;
2158  outputBuffer.callback = callback;
2160 
2161  retVal = EnqueueBuffer(handle->rxQueue, &outputBuffer, &queueBuffer);
2162  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2163  {
2164  return retVal;
2165  }
2166  if (!(handle->rxDmaActive))
2167  {
2168  EnableReceiver(handle);
2169  StartReceiveDma(handle, queueBuffer);
2170 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
2171  if (handle->fcType != uartdrvFlowControlHwUart)
2172  {
2173  handle->fcSelfState = uartdrvFlowControlOn;
2174  FcApplyState(handle);
2175  }
2176 #endif
2177  } // else: started by ReceiveDmaComplete
2178 
2179  return ECODE_EMDRV_UARTDRV_OK;
2180 }
2181 
2182 
2183 /***************************************************************************/
2197  uint8_t *data,
2198  UARTDRV_Count_t count)
2199 {
2200  Ecode_t retVal;
2201  UARTDRV_Buffer_t inputBuffer;
2202  UARTDRV_Buffer_t *queueBuffer;
2203 
2204  retVal = CheckParams(handle, data, count);
2205  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2206  {
2207  return retVal;
2208  }
2209  inputBuffer.data = data;
2210  inputBuffer.transferCount = count;
2211  inputBuffer.itemsRemaining = count;
2212  inputBuffer.callback = NULL;
2214 
2215  retVal = EnqueueBuffer(handle->rxQueue, &inputBuffer, &queueBuffer);
2216  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2217  {
2218  return retVal;
2219  }
2220  while (handle->rxQueue->used > 1)
2221  {
2222  EMU_EnterEM1();
2223  }
2224  EnableReceiver(handle);
2225 #if (EMDRV_UARTDRV_FLOW_CONTROL_ENABLE)
2226  if (handle->fcType != uartdrvFlowControlHwUart)
2227  {
2228  handle->fcSelfState = uartdrvFlowControlOn;
2229  FcApplyState(handle);
2230  }
2231 #endif
2232  StartReceiveDma(handle, queueBuffer);
2233  while (handle->rxDmaActive)
2234  {
2235  EMU_EnterEM1();
2236  }
2237  return queueBuffer->transferStatus;
2238 }
2239 
2240 /***************************************************************************/
2251 {
2252  if (handle == NULL)
2253  {
2255  }
2256  bool active = false;
2257  Ecode_t status = DMADRV_TransferActive( handle->txDmaCh , &active );
2258  if ( (status == ECODE_EMDRV_DMADRV_OK) && (handle->txDmaPaused > 0) && active )
2259  {
2260  // Resume the transfer if 1) pause counter is 1
2261  // 2) HW flow control doesn't need to pause the DMA
2262  if ( (handle->txDmaPaused == 1) && (HwFcGetClearToSendPin(handle) == uartdrvFlowControlOn) )
2263  {
2264  DMADRV_ResumeTransfer(handle->txDmaCh);
2265  }
2266  handle->txDmaPaused--;
2267  }
2268  else
2269  {
2271  }
2272  return ECODE_EMDRV_UARTDRV_OK;
2273 }
2274 
2275 /***************************************************************************/
2291  uint8_t *data,
2292  UARTDRV_Count_t count,
2293  UARTDRV_Callback_t callback)
2294 {
2295  Ecode_t retVal;
2296  UARTDRV_Buffer_t inputBuffer;
2297  UARTDRV_Buffer_t *queueBuffer;
2298 
2299  retVal = CheckParams(handle, data, count);
2300  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2301  {
2302  return retVal;
2303  }
2304  inputBuffer.data = data;
2305  inputBuffer.transferCount = count;
2306  inputBuffer.itemsRemaining = count;
2307  inputBuffer.callback = callback;
2309 
2310  retVal = EnqueueBuffer(handle->txQueue, &inputBuffer, &queueBuffer);
2311  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2312  {
2313  return retVal;
2314  }
2315  if (!(handle->txDmaActive))
2316  {
2318  if (handle->txQueue->used > 0)
2319  {
2320  StartTransmitDma(handle, queueBuffer);
2321  handle->hasTransmitted = true;
2322  }
2323  )
2324  } // else: started by TransmitDmaComplete
2325 
2326  return ECODE_EMDRV_UARTDRV_OK;
2327 }
2328 
2329 
2330 /***************************************************************************/
2344  uint8_t *data,
2345  UARTDRV_Count_t count)
2346 {
2347  Ecode_t retVal;
2348  UARTDRV_Buffer_t outputBuffer;
2349  UARTDRV_Buffer_t *queueBuffer;
2350 
2351  retVal = CheckParams(handle, data, count);
2352  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2353  {
2354  return retVal;
2355  }
2356  outputBuffer.data = data;
2357  outputBuffer.transferCount = count;
2358  outputBuffer.itemsRemaining = count;
2359  outputBuffer.callback = NULL;
2361 
2362  retVal = EnqueueBuffer(handle->txQueue, &outputBuffer, &queueBuffer);
2363  if (retVal != ECODE_EMDRV_UARTDRV_OK)
2364  {
2365  return retVal;
2366  }
2367  while (handle->txQueue->used > 1)
2368  {
2369  EMU_EnterEM1();
2370  }
2371  StartTransmitDma(handle, queueBuffer);
2372  handle->hasTransmitted = true;
2373  while (handle->txDmaActive)
2374  {
2375  EMU_EnterEM1();
2376  }
2377  return queueBuffer->transferStatus;
2378 }
2379 
2380 
2381 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/
Byte.
Definition: dmadrv.h:510
void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
Select reference clock/oscillator used for a clock branch.
Definition: em_cmu.c:2521
Software XON/XOFF.
Definition: uartdrv.h:75
USART_Stopbits_TypeDef stopbits
Definition: em_usart.h:317
Trig on USART1_RXDATAV.
Definition: dmadrv.h:459
XOFF or nRTS/nCTS high.
Definition: uartdrv.h:84
uint8_t portLocationRx
Location number for UART Rx pin.
Definition: uartdrv.h:182
#define UARTDRV_STATUS_RXDATAV
Data is available in receive buffer.
Definition: uartdrv.h:64
#define _USART_ROUTELOC1_RTSLOC_SHIFT
USART_TypeDef * port
The peripheral used for UART.
Definition: uartdrv.h:178
Ecode_t UARTDRV_Transmit(UARTDRV_Handle_t handle, uint8_t *data, UARTDRV_Count_t count, UARTDRV_Callback_t callback)
Start a non-blocking transmit.
Definition: uartdrv.c:2290
#define LEUART_IFC_PERR
void LEUART_Tx(LEUART_TypeDef *leuart, uint8_t data)
Transmit one frame.
Definition: em_leuart.c:609
#define ECODE_EMDRV_UARTDRV_PARAM_ERROR
Illegal input parameter.
Definition: uartdrv.h:45
void USART_Tx(USART_TypeDef *usart, uint8_t data)
Transmit one 4-9 bit frame.
Definition: em_usart.c:1084
uint8_t UARTDRV_GetTransmitDepth(UARTDRV_Handle_t handle)
Returns the number of queued transmit operations.
Definition: uartdrv.c:1751
uint8_t ctsPin
CTS pin number.
Definition: uartdrv.h:194
__IM uint32_t SYNCBUSY
#define CORE_DECLARE_IRQ_STATE
Definition: em_core.h:85
#define LEUART_ROUTEPEN_TXPEN
#define _USART_ROUTELOC0_RXLOC_MASK
GPIO_Port_TypeDef
Definition: em_gpio.h:345
#define LEUART_CMD_CLEARRX
enum UARTDRV_AbortType UARTDRV_AbortType_t
Transfer abort type.
LEUART_Stopbits_TypeDef stopbits
Definition: em_leuart.h:128
Abort all current and queued operations.
Definition: uartdrv.h:93
Ecode_t transferStatus
Completion status of transfer operation.
Definition: uartdrv.h:139
uint8_t ctsPin
CTS pin number.
Definition: uartdrv.h:230
GPIO_Port_TypeDef rtsPort
RTS pin port number.
Definition: uartdrv.h:195
#define USART1
Ecode_t DMADRV_PeripheralMemory(unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *dst, void *src, bool dstInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam)
Start a peripheral to memory DMA transfer.
Definition: dmadrv.c:539
#define USART_ROUTEPEN_CTSPEN
#define ECODE_EMDRV_UARTDRV_QUEUE_EMPTY
UART operation queue is empty.
Definition: uartdrv.h:51
uint32_t baudRate
UART baud rate.
Definition: uartdrv.h:179
UARTDRV_Buffer_FifoQueue_t * rxQueue
Receive operation queue.
Definition: uartdrv.h:233
__IOM uint32_t ROUTELOC0
USART_OVS_TypeDef oversampling
Definition: em_usart.h:307
UARTDRV_Buffer_t fifo[]
FIFO of queue data.
Definition: uartdrv.h:149
Ecode_t DMADRV_TransferActive(unsigned int channelId, bool *active)
Check if a transfer is running.
Definition: dmadrv.c:759
Trig on USART0_RXDATAV.
Definition: dmadrv.h:450
#define USART_STATUS_TXENS
UARTDRV_FlowControlState_t UARTDRV_FlowControlGetSelfStatus(UARTDRV_Handle_t handle)
Checks the self's flow control status.
Definition: uartdrv.c:1894
#define _USART_ROUTELOC0_TXLOC_SHIFT
#define USART_STATUS_RXDATAV
USART_Parity_TypeDef parity
Parity configuration.
Definition: uartdrv.h:187
__STATIC_INLINE void USART_IntClear(USART_TypeDef *usart, uint32_t flags)
Clear one or more pending USART interrupts.
Definition: em_usart.h:757
USART_Stopbits_TypeDef stopBits
Number of stop bits.
Definition: uartdrv.h:186
#define LEUART_ROUTEPEN_RXPEN
USART_Databits_TypeDef databits
Definition: em_usart.h:311
#define ECODE_EMDRV_UARTDRV_FRAME_ERROR
UART frame error. Data is ignored.
Definition: uartdrv.h:53
#define USART_ROUTEPEN_TXPEN
#define USART0
#define _USART_ROUTELOC1_CTSLOC_SHIFT
Ecode_t DMADRV_StopTransfer(unsigned int channelId)
Stop an ongoing DMA transfer.
Definition: dmadrv.c:719
#define USART_CTRLX_CTSEN
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define LEUART_STATUS_RXDATAV
USART_Parity_TypeDef parity
Definition: em_usart.h:314
volatile UARTDRV_Count_t itemsRemaining
Transfer items remaining.
Definition: uartdrv.h:137
#define ECODE_EMDRV_UARTDRV_OK
Success return value.
Definition: uartdrv.h:42
#define USART_CMD_TXDIS
void GPIOINT_CallbackRegister(uint8_t pin, GPIOINT_IrqCallbackPtr_t callbackPtr)
Registers user callback for given pin number.
Definition: gpiointerrupt.c:91
USART_Enable_TypeDef enable
Definition: em_usart.h:295
#define UARTDRV_STATUS_RXBLOCK
Receiver is blocked; incoming frames will be discarded.
Definition: uartdrv.h:60
UARTDRV_FlowControlType_t fcType
Flow control mode.
Definition: uartdrv.h:192
Ecode_t UARTDRV_InitUart(UARTDRV_Handle_t handle, const UARTDRV_InitUart_t *initData)
Initialize a U(S)ART driver instance.
Definition: uartdrv.c:1015
Ecode_t UARTDRV_FlowControlSet(UARTDRV_Handle_t handle, UARTDRV_FlowControlState_t state)
Set UART flow control state. Set nRTS pin if hardware flow control is enabled. Send XON/XOFF if softw...
Definition: uartdrv.c:1816
uint32_t CMU_ClkDiv_TypeDef
Definition: em_cmu.h:167
uint32_t baudRate
UART baud rate.
Definition: uartdrv.h:219
#define USART_STATUS_TXC
#define _LEUART_ROUTELOC0_RXLOC_MASK
const uint16_t size
Size of FIFO.
Definition: uartdrv.h:148
uint8_t rtsPin
RTS pin number.
Definition: uartdrv.h:196
__STATIC_INLINE void LEUART_IntClear(LEUART_TypeDef *leuart, uint32_t flags)
Clear one or more pending LEUART interrupts.
Definition: em_leuart.h:169
GPIO_Port_TypeDef ctsPort
CTS pin port number.
Definition: uartdrv.h:229
#define USART_IF_FERR
This driver controls the state.
Definition: uartdrv.h:85
UARTDRV_Count_t transferCount
Transfer item count.
Definition: uartdrv.h:136
LEUART_Stopbits_TypeDef stopBits
Number of stop bits.
Definition: uartdrv.h:226
uint32_t SystemLFXOClockGet(void)
Get low frequency crystal oscillator clock frequency for target system.
#define USART_IFC_PERR
void LEUART_Init(LEUART_TypeDef *leuart, LEUART_Init_TypeDef const *init)
Init LEUART.
Definition: em_leuart.c:461
enum UARTDRV_FlowControlState UARTDRV_FlowControlState_t
Flow Control state.
Transfer operation FIFO queue typedef.
Definition: uartdrv.h:143
#define UARTDRV_STATUS_TXEN
Transmitter is enabled.
Definition: uartdrv.h:59
UARTDRV_HandleData_t * UARTDRV_Handle_t
Handle pointer.
Definition: uartdrv.h:277
Ecode_t DMADRV_TransferRemainingCount(unsigned int channelId, int *remaining)
Get number of items remaining in a transfer.
Definition: dmadrv.c:930
#define LEUART_IF_FERR
Ecode_t DMADRV_ResumeTransfer(unsigned int channelId)
Resume an ongoing DMA transfer.
Definition: dmadrv.c:682
UARTDRV_Buffer_FifoQueue_t * txQueue
Transmit operation queue.
Definition: uartdrv.h:198
uint8_t rtsPin
RTS pin number.
Definition: uartdrv.h:232
#define LEUART_CMD_CLEARTX
nRTS/nCTS hardware handshake
Definition: uartdrv.h:76
Ecode_t UARTDRV_ForceTransmit(UARTDRV_Handle_t handle, uint8_t *data, UARTDRV_Count_t count)
Direct transmit without interrupts or callback. Blocking function that ignores flow control if enable...
Definition: uartdrv.c:2015
LEUART_TypeDef * port
The peripheral used for LEUART.
Definition: uartdrv.h:218
#define UARTDRV_STATUS_TXC
Transmit operation is complete, no more data is available in the transmit buffer and shift register...
Definition: uartdrv.h:62
#define ECODE_EMDRV_UARTDRV_DMA_ALLOC_ERROR
Unable to allocated DMA channels.
Definition: uartdrv.h:54
__IOM uint32_t ROUTEPEN
#define LEUART_STATUS_TXC
#define ECODE_EMDRV_UARTDRV_CLOCK_ERROR
Unable to set desired baudrate.
Definition: uartdrv.h:55
XON or nRTS/nCTS low.
Definition: uartdrv.h:83
#define CORE_ENTER_ATOMIC()
Definition: em_core.h:138
LEUART_Databits_TypeDef
Definition: em_leuart.h:61
#define ECODE_EMDRV_UARTDRV_QUEUE_FULL
UART operation queue is full.
Definition: uartdrv.h:50
#define LEUART_STATUS_TXIDLE
#define CMU_STATUS_LFXOENS
volatile uint16_t head
Index of next byte to send.
Definition: uartdrv.h:145
#define CORE_ATOMIC_SECTION(yourcode)
Definition: em_core.h:126
void GPIO_PinModeSet(GPIO_Port_TypeDef port, unsigned int pin, GPIO_Mode_TypeDef mode, unsigned int out)
Set the mode for a GPIO pin.
Definition: em_gpio.c:269
uint8_t portLocationRts
Location number for UART RTS pin.
Definition: uartdrv.h:201
#define ECODE_EMDRV_UARTDRV_PARITY_ERROR
UART parity error frame. Data is ignored.
Definition: uartdrv.h:52
Ecode_t UARTDRV_ReceiveB(UARTDRV_Handle_t handle, uint8_t *data, UARTDRV_Count_t count)
Start a blocking receive.
Definition: uartdrv.c:2196
GPIO_Port_TypeDef rtsPort
RTS pin port number.
Definition: uartdrv.h:231
Trig on USART1_TXBL.
Definition: dmadrv.h:465
__STATIC_INLINE void EMU_EnterEM1(void)
Enter energy mode 1 (EM1).
Definition: em_emu.h:713
General Purpose IO (GPIO) peripheral API.
#define LEUART_STATUS_RXENS
#define _LEUART_ROUTELOC0_RXLOC_SHIFT
#define USART_IF_PERR
#define LEUART_STATUS_TXENS
UARTDRV API definition.
uint8_t portLocationCts
Location number for UART CTS pin.
Definition: uartdrv.h:200
uint8_t portLocationTx
Location number for UART Tx pin.
Definition: uartdrv.h:181
uint32_t Ecode_t
Typedef for API function error code return values.
Definition: ecode.h:51
The UART peripheral controls nRTS/nCTS.
Definition: uartdrv.h:77
Trig on USART0_TXBL.
Definition: dmadrv.h:453
USART_Databits_TypeDef
Definition: em_usart.h:105
UARTDRV_Callback_t callback
Completion callback.
Definition: uartdrv.h:138
#define LEUART_CTRL_DATABITS_EIGHT
#define CMU
#define DMADRV_MAX_XFER_COUNT
Maximum length of one DMA transfer.
Definition: dmadrv.h:311
__STATIC_INLINE void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin)
Set a single pin in GPIO data out register to 1.
Definition: em_gpio.h:856
#define USART_STATUS_RXENS
#define _USART_ROUTELOC0_TXLOC_MASK
Core interrupt handling API.
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Definition: em_cmu.c:1453
LEUART_Parity_TypeDef parity
Definition: em_leuart.h:125
Ecode_t DMADRV_Init(void)
Initialize DMADRV.
Definition: dmadrv.c:262
void LEUART_Enable(LEUART_TypeDef *leuart, LEUART_Enable_TypeDef enable)
Enable/disable LEUART receiver and/or transmitter.
Definition: em_leuart.c:357
__IOM uint32_t ROUTELOC0
__IOM uint32_t ROUTEPEN
volatile uint16_t used
Number of bytes queued.
Definition: uartdrv.h:147
#define LEUART0
UARTDRV_FlowControlType_t fcType
Flow control mode.
Definition: uartdrv.h:228
#define _CMU_LFBPRESC0_LEUART0_SHIFT
UART transfer buffer.
Definition: uartdrv.h:133
volatile uint16_t tail
Index of where to enqueue next message.
Definition: uartdrv.h:146
void(* UARTDRV_Callback_t)(struct UARTDRV_HandleData *handle, Ecode_t transferStatus, uint8_t *data, UARTDRV_Count_t transferCount)
UARTDRV transfer completion callback function.
Definition: uartdrv.h:127
#define UARTDRV_STATUS_TXIDLE
Transmitter is idle.
Definition: uartdrv.h:66
void LEUART_Reset(LEUART_TypeDef *leuart)
Reset LEUART to same state as after a HW reset.
Definition: em_leuart.c:500
__STATIC_INLINE void GPIO_IntConfig(GPIO_Port_TypeDef port, unsigned int pin, bool risingEdge, bool fallingEdge, bool enable)
Configure GPIO interrupt.
Definition: em_gpio.h:1104
#define UARTDRV_STATUS_TXBL
Transmit buffer is empty.
Definition: uartdrv.h:63
__IOM uint32_t ROUTELOC1
Ecode_t UARTDRV_Receive(UARTDRV_Handle_t handle, uint8_t *data, UARTDRV_Count_t count, UARTDRV_Callback_t callback)
Start a non-blocking receive.
Definition: uartdrv.c:2141
#define _LEUART_ROUTELOC0_TXLOC_MASK
#define LEUART_SYNCBUSY_CMD
#define CORE_EXIT_ATOMIC()
Definition: em_core.h:142
Ecode_t UARTDRV_DeInit(UARTDRV_Handle_t handle)
Deinitialize a UART driver instance.
Definition: uartdrv.c:1446
Abort current and queued receive operations.
Definition: uartdrv.h:92
#define ECODE_EMDRV_DMADRV_OK
Success return value.
Definition: dmadrv.h:50
LEUART_Parity_TypeDef parity
Parity configuration.
Definition: uartdrv.h:227
UARTDRV_Count_t UARTDRV_ForceReceive(UARTDRV_Handle_t handle, uint8_t *data, UARTDRV_Count_t maxCount)
Direct receive without interrupts or callback. Blocking function.
Definition: uartdrv.c:1930
UARTDRV_Status_t UARTDRV_GetPeripheralStatus(UARTDRV_Handle_t handle)
Returns the status of the UART peripheral associated with a given handle.
Definition: uartdrv.c:1624
bool CORE_IrqIsBlocked(IRQn_Type irqN)
Check if a specific interrupt is disabled or blocked.
Definition: em_core.c:662
#define LEUART_IF_PERR
#define LEUART_CMD_TXEN
#define USART_CMD_RXEN
#define _LEUART_ROUTELOC0_TXLOC_SHIFT
Ecode_t DMADRV_DeInit(void)
Deinitialize DMADRV.
Definition: dmadrv.c:177
#define UARTDRV_STATUS_RXEN
Receiver is enabled.
Definition: uartdrv.h:58
Energy management unit (EMU) peripheral API.
uint32_t UARTDRV_Count_t
UART transfer count.
Definition: uartdrv.h:68
#define ECODE_EMDRV_UARTDRV_WAITING
Operation is waiting in queue.
Definition: uartdrv.h:43
UARTDRV_Status_t UARTDRV_GetReceiveStatus(UARTDRV_Handle_t handle, uint8_t **buffer, UARTDRV_Count_t *itemsReceived, UARTDRV_Count_t *itemsRemaining)
Check the status of the UART and gather information about any ongoing receive operations.
Definition: uartdrv.c:1709
#define LEUART_CMD_RXEN
Ecode_t UARTDRV_PauseTransmit(UARTDRV_Handle_t handle)
Pause an ongoing transmit operation.
Definition: uartdrv.c:2098
Ecode_t DMADRV_AllocateChannel(unsigned int *channelId, void *capabilities)
Allocate (reserve) a DMA channel.
Definition: dmadrv.c:131
uint8_t UARTDRV_GetReceiveDepth(UARTDRV_Handle_t handle)
Returns the number of queued receive operations.
Definition: uartdrv.c:1687
static volatile uint8_t rxBuffer[RXBUFSIZE]
void GPIOINT_Init(void)
Initialization of GPIOINT module.
Definition: gpiointerrupt.c:67
#define USART_ROUTEPEN_RTSPEN
#define USART_ROUTEPEN_RXPEN
Ecode_t DMADRV_MemoryPeripheral(unsigned int channelId, DMADRV_PeripheralSignal_t peripheralSignal, void *dst, void *src, bool srcInc, int len, DMADRV_DataSize_t size, DMADRV_Callback_t callback, void *cbUserParam)
Start a memory to peripheral DMA transfer.
Definition: dmadrv.c:406
uint8_t * data
Transfer data buffer.
Definition: uartdrv.h:135
GPIOINT API definition.
GPIO_Port_TypeDef ctsPort
CTS pin port number.
Definition: uartdrv.h:193
__IOM uint32_t CMD
uint8_t portLocationRx
Location number for LEUART Rx pin.
Definition: uartdrv.h:222
#define USART_INITASYNC_DEFAULT
Definition: em_usart.h:356
#define ECODE_EMDRV_UARTDRV_ABORTED
UART transfer has been aborted.
Definition: uartdrv.h:49
#define USART_IFC_FERR
#define LEUART_CMD_TXDIS
Ecode_t UARTDRV_Abort(UARTDRV_Handle_t handle, UARTDRV_AbortType_t type)
Abort ongoing UART transfers.
Definition: uartdrv.c:1511
uint8_t portLocationTx
Location number for LEUART Tx pin.
Definition: uartdrv.h:221
UARTDRV_Status_t UARTDRV_GetTransmitStatus(UARTDRV_Handle_t handle, uint8_t **buffer, UARTDRV_Count_t *itemsSent, UARTDRV_Count_t *itemsRemaining)
Check the status of the UART and gather information about any ongoing transmit operations.
Definition: uartdrv.c:1772
Ecode_t UARTDRV_InitLeuart(UARTDRV_Handle_t handle, const UARTDRV_InitLeuart_t *initData)
Initialize a LEUART driver instance.
Definition: uartdrv.c:1249
UARTDRV_FlowControlState_t UARTDRV_FlowControlGetPeerStatus(UARTDRV_Handle_t handle)
Checks the peer's flow control status.
Definition: uartdrv.c:1879
#define USART_FRAME_DATABITS_EIGHT
UARTDRV_Buffer_FifoQueue_t * rxQueue
Receive operation queue.
Definition: uartdrv.h:197
Ecode_t UARTDRV_TransmitB(UARTDRV_Handle_t handle, uint8_t *data, UARTDRV_Count_t count)
Start a blocking transmit.
Definition: uartdrv.c:2343
__STATIC_INLINE void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin)
Set a single pin in GPIO data out port register to 0.
Definition: em_gpio.h:811
void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
Enable/disable USART/UART receiver and/or transmitter.
Definition: em_usart.c:527
void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
Init USART/UART for normal asynchronous mode.
Definition: em_usart.c:569
Ecode_t UARTDRV_FlowControlIgnoreRestrain(UARTDRV_Handle_t handle)
Enables transmission when restrained by flow control.
Definition: uartdrv.c:1909
#define LEUART_INIT_DEFAULT
Definition: em_leuart.h:132
#define ECODE_EMDRV_UARTDRV_ILLEGAL_OPERATION
Illegal operation on UART port.
Definition: uartdrv.h:47
Trig on LEUART0_TXBL.
Definition: dmadrv.h:381
#define LEUART_CMD_RXDIS
UARTDRV_Buffer_FifoQueue_t * txQueue
Transmit operation queue.
Definition: uartdrv.h:234
#define USART_CMD_RXDIS
Trig on LEUART0_RXDATAV.
Definition: dmadrv.h:378
uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
Get clock frequency for a clock point.
Definition: em_cmu.c:1550
#define USART_CMD_TXEN
__STATIC_INLINE unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
Read the pad value for a single pin in a GPIO port.
Definition: em_gpio.h:781
#define ECODE_EMDRV_UARTDRV_ILLEGAL_HANDLE
Illegal UART handle.
Definition: uartdrv.h:44
__IOM uint32_t CMD
#define LEUART_STATUS_RXBLOCK
Abort current and queued transmit operations.
Definition: uartdrv.h:91
#define USART_CMD_CLEARRX
#define _USART_ROUTELOC0_RXLOC_SHIFT
__IOM uint32_t CTRLX
#define LEUART_STATUS_TXBL
#define LEUART_IFC_FERR
#define ECODE_EMDRV_UARTDRV_IDLE
No UART transfer in progress.
Definition: uartdrv.h:48
uint32_t UARTDRV_Status_t
UART status return type. Bitfield of UARTDRV_STATUS_* values.
Definition: uartdrv.h:69
void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
Set clock divisor/prescaler.
Definition: em_cmu.c:1244
Ecode_t DMADRV_PauseTransfer(unsigned int channelId)
Pause an ongoing DMA transfer.
Definition: dmadrv.c:645
Ecode_t UARTDRV_ResumeTransmit(UARTDRV_Handle_t handle)
Resume a paused transmit operation.
Definition: uartdrv.c:2250
bool mvdis
Majority Vote Disable for 16x, 8x and 6x oversampling modes.
Definition: uartdrv.h:190
Ecode_t DMADRV_FreeChannel(unsigned int channelId)
Free an allocate (reserved) DMA channel.
Definition: dmadrv.c:225
LEUART_Databits_TypeDef databits
Definition: em_leuart.h:122
USART_OVS_TypeDef oversampling
Oversampling mode.
Definition: uartdrv.h:188
Ecode_t UARTDRV_FlowControlSetPeerStatus(UARTDRV_Handle_t handle, UARTDRV_FlowControlState_t state)
Set peer UART flow control state. Pause/resume transmit accordingly. Only for manual software flow co...
Definition: uartdrv.c:1846
LEUART_Enable_TypeDef enable
Definition: em_leuart.h:110
#define USART_CMD_CLEARTX
#define _CMU_LFBPRESC0_LEUART0_MASK