ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_uart.c
1 
57 #include <drivers/uart/adi_uart.h>
58 #include <drivers/dma/adi_dma.h>
59 #include "adi_uart_def.h"
60 #include <adi_cyclecount.h>
61 
62 
63 #ifdef __ICCARM__
64 /*
65 * IAR MISRA C 2004 error suppressions.
66 *
67 * Pm50: (MISRA C 2004 rule 14.3): a null statement shall only occur on a line by itself,
68 * and shall not have any other text on the same line
69 * Some Macros, such as ISR_PROLOGUE, may not have any expansion
70 * resulting in just the terminating ';'.
71 *
72 * Pm073 (rule 14.7): A function should have a single point of exit.
73 * Pm143 (rule 14.7): A function should have a single point of exit at the end of the function.
74 * Multiple returns are used for error handling.
75 *
76 * Pm088 (rule 17.4): Pointer arithmetic should not be used.
77 * Relying on pointer arithmetic for buffer handling.
78 *
79 * Pm123 (rule 18.5): There shall be no definition of objects in a header file.
80 *
81 * Pm140 (rule 11.3): A cast should not be performed between a pointer type and an integral type.
82 * MMR addresses are defined as simple constants. Accessing the MMR requires casting to a pointer type.
83 *
84 * Pm152 (rule 17.4): Array indexing shall only be applied to objects defined as an array type.
85 * Relying on pointer arithmetic for buffer handling and
86 * Accessing the DMA descriptors, which are defined in the system as a pointer to an array of descriptors.
87 *
88 * Pm008: Code should not be commented out.
89  This code was commented out to show what the autobaud equations would look like if there were floating point precision.
90  Ideally this would be the case but for the sake of footprint size we will leave it at single point precision.
91 */
92 #pragma diag_suppress=Pm050,Pm073,Pm088,Pm123,Pm140,Pm143,Pm152,Pm008,Pm026
93 #endif /* __ICCARM__ */
94 
95 
96 
97 
98 /**********************************************************
99  * UART Data
100  **********************************************************/
101 static ADI_UART_DEVICE_INFO uart_device_info[ ] =
102 {
103  {
104  UART0_TX_CHANn,
105  UART0_RX_CHANn,
106  DMA0_CH8_DONE_IRQn,
107  DMA0_CH9_DONE_IRQn,
108  (IRQn_Type)INTR_UART0_EVT,
109  pADI_UART0,
110  NULL
111  },
112 #if defined (__ADUCM4x50__)
113  {
114  UART1_TX_CHANn,
115  UART1_RX_CHANn,
116  DMA0_CH25_DONE_IRQn,
117  DMA0_CH26_DONE_IRQn,
118  (IRQn_Type)INTR_UART1_EVT,
119  pADI_UART1,
120  NULL
121  },
122 #endif /* __ADUCM4x50 */
123 };
124 
125 static const ADI_UART_CONFIG gUARTCfg[ ] =
126 {
127  {
128  /* Line control register. */
129  ((ADI_UART0_CFG_WORD_LENGTH << BITP_UART_LCR_WLS) |
130  (ADI_UART0_CFG_STOP_BIT << BITP_UART_LCR_STOP) |
131  (ADI_UART0_CFG_ENABLE_PARITY << BITP_UART_LCR_PEN) |
132  (ADI_UART0_CFG_PARITY_SELECTION << BITP_UART_LCR_EPS) |
133  (ADI_UART0_CFG_ENABLE_STICKY_PARITY << BITP_UART_LCR_SP)),
134 
135  /* Div-C in baudrate divider register. */
137 
138  /* Div-M and Div-N in fractional baudrate Register. */
139  (((uint32_t)ADI_UART0_CFG_DIVN << BITP_UART_FBR_DIVN) |
140  ((uint32_t)ADI_UART0_CFG_DIVM << BITP_UART_FBR_DIVM) |
141  ((uint32_t)BITM_UART_FBR_FBEN)),
142 
143  /* Over sample rate in second line control register. */
145 
146  /* FIFO control register. */
147  ((ADI_UART0_CFG_ENABLE_FIFO << BITP_UART_FCR_FIFOEN)|
148  (ADI_UART0_CFG_TRIG_LEVEL << BITP_UART_FCR_RFTRIG)),
149 
150  /* Half duplex control register. */
151  ((ADI_UART0_CFG_SOUT_POLARITY << BITP_UART_RSC_OENP) |
152  (ADI_UART0_CFG_DEASSERTION << BITP_UART_RSC_OENSP) |
153  (ADI_UART0_CFG_DISABLE_RX << BITP_UART_RSC_DISRX) |
154  (ADI_UART0_CFG_HOLD_TX << BITP_UART_RSC_DISTX)),
155 
156  /* Interrupt enable register. */
157  ((ADI_UART0_CFG_ENABLE_MODEM_STATUS_INTERRUPT << BITP_UART_IEN_EDSSI) |
158  (ADI_UART0_CFG_ENABLE_RX_STATUS_INTERRUPT << BITP_UART_IEN_ELSI))
159 
160  },
161 #if defined (__ADUCM4x50__)
162  {
163  /* Line control register. */
164  ((ADI_UART1_CFG_WORD_LENGTH << BITP_UART_LCR_WLS) |
165  (ADI_UART1_CFG_STOP_BIT << BITP_UART_LCR_STOP) |
166  (ADI_UART1_CFG_ENABLE_PARITY << BITP_UART_LCR_PEN) |
167  (ADI_UART1_CFG_PARITY_SELECTION << BITP_UART_LCR_EPS) |
168  (ADI_UART1_CFG_ENABLE_STICKY_PARITY << BITP_UART_LCR_SP)),
169 
170  /* Div-C in Baudrate divider register. */
172 
173  /* Div-M and Div-N in fractional baudrate Register. */
174  (((uint32_t)ADI_UART1_CFG_DIVN << BITP_UART_FBR_DIVN) |
175  ((uint32_t)ADI_UART1_CFG_DIVM << BITP_UART_FBR_DIVM) |
176  ((uint32_t)BITM_UART_FBR_FBEN)),
177 
178  /* Over sample rate in second line control register. */
180 
181  /* FIFO control register. */
182  ((ADI_UART1_CFG_ENABLE_FIFO << BITP_UART_FCR_FIFOEN)|
183  (ADI_UART1_CFG_TRIG_LEVEL << BITP_UART_FCR_RFTRIG)),
184 
185  /* Half duplex control register. */
186  ((ADI_UART1_CFG_SOUT_POLARITY << BITP_UART_RSC_OENP) |
187  (ADI_UART1_CFG_DEASSERTION << BITP_UART_RSC_OENSP) |
188  (ADI_UART1_CFG_DISABLE_RX << BITP_UART_RSC_DISRX) |
189  (ADI_UART1_CFG_HOLD_TX << BITP_UART_RSC_DISTX)),
190 
191  /* Interrupt enable register. */
192  ((ADI_UART1_CFG_ENABLE_MODEM_STATUS_INTERRUPT << BITP_UART_IEN_EDSSI) |
193  (ADI_UART1_CFG_ENABLE_RX_STATUS_INTERRUPT << BITP_UART_IEN_ELSI))
194  }
195 #endif /*__ADUCM4x50*/
196 };
197 
198 /* Number of bytes received before Rx interrupt triggers. */
199 static const uint8_t sFifoTriggers[] = {1u, 4u, 8u, 14u};
200 
204 #define ADI_UART_NUM_DEVICES (sizeof(uart_device_info)/sizeof(ADI_UART_DEVICE_INFO))
205 
206 /* Override "weak" default binding in startup.c */
208 extern void UART0_Int_Handler(void);
209 extern void UART1_Int_Handler(void);
210 extern void DMA_UART0_TX_Int_Handler(void);
211 extern void DMA_UART0_RX_Int_Handler(void);
212 
213 #if defined (__ADUCM4x50__)
214 extern void DMA_UART1_TX_Int_Handler(void);
215 extern void DMA_UART1_RX_Int_Handler(void);
216 #endif
217 
218 /* Internal DMA Callback for receiving DMA faults from common DMA error handler. */
219 static void RxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg);
220 static void RxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg) {
221 
222  /* Recover the device handle. */
223  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)pCBParam;
224  ADI_UART_BUFF_INFO * pNextBuff = hDevice->pChannelRx->pFillBuffer->pNextBuffer;
225  uint32_t nEvent = 0u;
226 
227  /* Save the DMA error. */
228  switch (Event) {
230  nEvent |= (uint32_t)ADI_UART_HW_ERR_RX_CHAN_DMA_BUS_FAULT;
231  break;
233  nEvent |= (uint32_t)ADI_UART_HW_ERR_RX_CHAN_DMA_INVALID_DESCR;
234  break;
235  default:
236  nEvent |= (uint32_t)ADI_UART_HW_ERR_RX_CHAN_DMA_UNKNOWN_ERROR;
237  break;
238  }
239 
240  if((pNextBuff->pStartAddress != NULL) && (pNextBuff->bDMA == true))
241  {
242  hDevice->nHwError |= nEvent;
243  pNextBuff->bInUse = false;
244  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
245 
246  }
247  hDevice->nHwError |= nEvent;
248  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
249 }
250 
251 static void TxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg);
252 static void TxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg) {
253 
254  /* Recover the device handle. */
255  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)pCBParam;
256  ADI_UART_BUFF_INFO * pNextBuff = hDevice->pChannelTx->pFillBuffer->pNextBuffer;
257  uint32_t nEvent = 0u;
258 
259  /* Save the DMA error. */
260  switch (Event) {
262  nEvent |= (uint32_t)ADI_UART_HW_ERR_TX_CHAN_DMA_BUS_FAULT;
263  break;
265  nEvent |= (uint32_t)ADI_UART_HW_ERR_TX_CHAN_DMA_INVALID_DESCR;
266  break;
267  default:
268  nEvent |= (uint32_t)ADI_UART_HW_ERR_TX_CHAN_DMA_UNKNOWN_ERROR;
269  break;
270  }
271  if((pNextBuff->pStartAddress != NULL) && (pNextBuff->bDMA == true))
272  {
273  hDevice->nHwError |= nEvent;
274  pNextBuff->bInUse = false;
275  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
276 
277  }
278 
279  hDevice->nHwError |= nEvent;
280  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
281 }
284 /**********************************************************
285  * General UART APIs
286  **********************************************************/
287 
316  uint32_t const nDeviceNum,
317  ADI_UART_DIRECTION const eDirection,
318  void *pMemory,
319  uint32_t const nMemSize,
320  ADI_UART_HANDLE *const phDevice
321  )
322 {
323  uint16_t regFifoTrig = 0u;
324 
325 #ifdef ADI_DEBUG
326  /* Check if the given device number is within the range of UART
327  * devices present in the processor. There are two devices present here
328  * so this can be a 0 or 1 for ADuCM4050 and only 0 for ADuCM302x.
329  */
330  if(nDeviceNum >= ADI_UART_NUM_DEVICES)
331  {
333  }
334 
335  /* Verify the device is not already open. */
336  if(uart_device_info[nDeviceNum].hDevice != NULL)
337  {
338  return(ADI_UART_DEVICE_IN_USE);
339  }
340 
341  /* Make sure there is enough memory for the device instance to operate in a single direction. */
342  if(eDirection != ADI_UART_DIR_BIDIRECTION)
343  {
344  if(nMemSize < (uint32_t)ADI_UART_UNIDIR_MEMORY_SIZE)
345  {
347  }
348  assert(nMemSize == (sizeof(ADI_UART_DEVICE) + sizeof(ADI_UART_DATA_CHANNEL)));
349  }
350 
351  /* Make sure there is enough memory for the device instance to operate in both directions. */
352  else
353  {
354  if(nMemSize < (uint32_t)ADI_UART_BIDIR_MEMORY_SIZE)
355  {
357  }
358  assert(nMemSize == (sizeof(ADI_UART_DEVICE) + (sizeof(ADI_UART_DATA_CHANNEL)*2u)));
359  }
360 #endif /* ADI_DEBUG */
361 
362  /* Initialize the device handle to NULL in case of a failure. */
363  *phDevice = NULL;
364 
365  /* Link the ADI_UART_HANDLE to the ADI_UART_DEVICE structure. */
366  ADI_UART_HANDLE hDevice = pMemory;
367 
368  /* Zero the device handle memory so we do not have to explicitely initialize
369  the structure members to 0.
370  */
371  memset(pMemory, 0, nMemSize);
372 
373 
374  /* Set the device information. */
375  hDevice->pUartInfo = &uart_device_info[nDeviceNum];
376 
377  /* Set the base of the UART register address. We do this to minimize
378  the cycle count when accessing the UART registers.
379  */
380  hDevice->pUARTRegs = uart_device_info[nDeviceNum].pUartRegs;
381 
382  /* Store the direction that this device will operate in. */
383  hDevice->eDirection = eDirection;
384 
385  /* Increment the device handle with the size of the UART device structure
386  so we can set the channel data next without overwriting
387  the #ADI_UART_DEVICE data.
388  */
389  pMemory = ((uint8_t *)pMemory +(sizeof(ADI_UART_DEVICE)));
390 
391  /* Set up the DMA Controller. */
392  adi_dma_Init();
393 
394  /* Initialize the TX-channel. */
395  if(ADI_UART_DIR_RECEIVE != eDirection)
396  {
397  hDevice->pChannelTx = (ADI_UART_DATA_CHANNEL *)pMemory;
398 
399  /* Initialize the data transfer mode. */
400  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
401 
402  /* Initialize Tx buffer pointers. */
403  hDevice->pChannelTx->pFreeBuffer = &hDevice->pChannelTx->PingPong[0];
404  hDevice->pChannelTx->pActiveBuffer = &hDevice->pChannelTx->PingPong[0];
405  hDevice->pChannelTx->pFillBuffer = &hDevice->pChannelTx->PingPong[0];
406 
407 
408  /* Create a "semaphore" (varies per OS) used for blocking buffer resource management. */
409  SEM_CREATE(hDevice->pChannelTx, "UART_TX_SEM", ADI_UART_SEMAPHORE_FAILED);
410 
411  /* Set submit buffer function pointer. */
412  hDevice->pChannelTx->pfSubmitBuffer = &uart_submittxbuffer;
413 
414  hDevice->pChannelTx->PingPong[0].pNextBuffer = &hDevice->pChannelTx->PingPong[1];
415  hDevice->pChannelTx->PingPong[1].pNextBuffer = &hDevice->pChannelTx->PingPong[0];
416 
417  /*Register DMA Callback. */
418  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(hDevice->pUartInfo->dmaTxChannelNum, TxDmaErrorCallback, (void*)hDevice))
419  {
420  adi_uart_Close(hDevice);
422  }
423 
424  /* Increment the device handle the size of #ADI_UART_DATA_CHANNEL
425  structure in case there is another channel to configure.
426  */
427  pMemory = ((uint8_t *)pMemory + sizeof(ADI_UART_DATA_CHANNEL));
428  }
429  /* Initialize the RX-channel. */
430  if(ADI_UART_DIR_TRANSMIT != eDirection)
431  {
432  hDevice->pChannelRx = (ADI_UART_DATA_CHANNEL *)pMemory;
433 
434  /* Initialize the data transfer mode. */
435  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
436 
437  /* Initialize Rx buffer pointers. */
438  hDevice->pChannelRx->pFreeBuffer = &hDevice->pChannelRx->PingPong[0];
439  hDevice->pChannelRx->pActiveBuffer = &hDevice->pChannelRx->PingPong[0];
440  hDevice->pChannelRx->pFillBuffer = &hDevice->pChannelRx->PingPong[0];
441 
442  /* Create a "semaphore" (varies per OS) used for blocking buffer resource management. */
443  SEM_CREATE(hDevice->pChannelRx, "UART_RX_SEM", ADI_UART_SEMAPHORE_FAILED);
444 
445  /* Set submit buffer function pointer. */
446  hDevice->pChannelRx->pfSubmitBuffer = &uart_submitrxbuffer;
447 
448  hDevice->pChannelRx->PingPong[0].pNextBuffer = &hDevice->pChannelRx->PingPong[1];
449  hDevice->pChannelRx->PingPong[1].pNextBuffer = &hDevice->pChannelRx->PingPong[0];
450 
451  /*Register DMA Callback. */
452  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(hDevice->pUartInfo->dmaRxChannelNum, RxDmaErrorCallback, (void*)hDevice))
453  {
454  adi_uart_Close(hDevice);
456  }
457  }
458 
459  /* Initialize the device with the static config values.*/
460  uart_init(hDevice, nDeviceNum);
461 
462  /* Extract the FIFO and FIFO trigger settings. These are required in
463  * the Rx interrupt handler to extract the right amount of data on an
464  * each Rx interrupt */
465  hDevice->bRxFifoEn = ((hDevice->pUARTRegs->FCR & BITM_UART_FCR_FIFOEN) > 0u);
466  regFifoTrig = ((hDevice->pUARTRegs->FCR & BITM_UART_FCR_RFTRIG) >> BITP_UART_FCR_RFTRIG);
467 
468  hDevice->nRxFifoTrig = sFifoTriggers[regFifoTrig];
469 
470  /* Write the device data pointer to the application's handle. */
471  *phDevice = hDevice;
472 
473  /* Store the device handle. */
474  uart_device_info[nDeviceNum].hDevice = hDevice;
475 
476 
477  /* Enable UART Interrupt. */
478  NVIC_ClearPendingIRQ(hDevice->pUartInfo->eIRQn);
479  NVIC_EnableIRQ(hDevice->pUartInfo->eIRQn);
480 
481  /* Enable the interrupt for the DMA. */
482  NVIC_EnableIRQ(hDevice->pUartInfo->eDMATx);
483  NVIC_EnableIRQ(hDevice->pUartInfo->eDMARx);
484 
485  /* Return SUCCESS */
486  return(ADI_UART_SUCCESS);
487 }
488 
508  ADI_UART_HANDLE const hDevice
509  )
510 {
511 #ifdef ADI_DEBUG
512  /* Validate the given handle. */
513  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
514  {
515  return(ADI_UART_INVALID_HANDLE);
516  }
517 
518  /* Make sure there are no active buffers on any active channel, autobaud is not in progress and the
519  Tx shift register is completely empty. This can be an issue if you submitted a nonblocking transmit
520  because you will receive interrupt before the hardware has fully finished the transaction. The start
521  address of the active buffer will remain in use until the buffer has been completely processed.
522  Therefore if the start address is NULL it means it has not been submitted for a transaction.
523  */
524  if(((hDevice->pUARTRegs->LSR & BITM_UART_LSR_TEMT) != BITM_UART_LSR_TEMT) ||
525  ((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pFillBuffer->pStartAddress != NULL)) ||
526  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pFillBuffer->pStartAddress != NULL)) ||
527  (hDevice->bAutobaudInProgress == true))
528  {
529  return(ADI_UART_DEVICE_IN_USE);
530  }
531 #endif /* ADI_DEBUG */
532 
533  /* Disable UART status interrupts. */
534  hDevice->pUARTRegs->IEN = 0x00U;
535 
536  /* Disable DMA UART interrupts. */
537  NVIC_DisableIRQ(hDevice->pUartInfo->eDMARx);
538  NVIC_DisableIRQ(hDevice->pUartInfo->eDMATx);
539 
540  /* Disable UART event interrupt. */
541  NVIC_DisableIRQ(hDevice->pUartInfo->eIRQn);
542 
543  /* Delete Tx-Channel semaphore. */
544  if(hDevice->eDirection != ADI_UART_DIR_RECEIVE)
545  {
546  SEM_DELETE(hDevice->pChannelTx, ADI_UART_SEMAPHORE_FAILED);
547  }
548 
549  /* Delete Rx-Channel semaphore. */
550  if(hDevice->eDirection != ADI_UART_DIR_TRANSMIT)
551  {
552  SEM_DELETE(hDevice->pChannelRx, ADI_UART_SEMAPHORE_FAILED);
553  }
554 
555  /* Free up the device memory. */
556  hDevice->pUartInfo->hDevice = NULL;
557 
558  return(ADI_UART_SUCCESS);
559 }
560 
595  ADI_UART_HANDLE const hDevice,
596  void *const pBuffer,
597  uint32_t const nBufSize,
598  bool const bDMA
599  )
600 {
601 
602 #ifdef ADI_DEBUG
603  /* Validate the device handle. */
604  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
605  {
606  return(ADI_UART_INVALID_HANDLE);
607  }
608 
609  /* Validate the pointer to the buffer memory. */
610  if(pBuffer == NULL)
611  {
612  return(ADI_UART_INVALID_POINTER);
613  }
614 
615  /* Validate the buffer size. */
616  if(nBufSize == 0U)
617  {
618  return(ADI_UART_FAILED);
619  }
620 
621  /* Autobaud in progress. */
622  if(hDevice->bAutobaudInProgress == true)
623  {
624  return(ADI_UART_DEVICE_IN_USE);
625  }
626 
627  /* Make sure we are transmitting. */
628  if(ADI_UART_DIR_RECEIVE == hDevice->eDirection)
629  {
631  }
632 
633  /* Check the data transfer mode (only allowed in nonblocking mode). */
634  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
635  {
637  }
638 
639  /* Check that there is a free buffer to use for this transmit operation. pFreeBuffer
640  is the next buffer available, so if it is in use we can make the assumption that
641  there are no buffers available. The start address is set to NULL once the buffer
642  has finished being processed in "adi_uart_GetBuffer()" or "adi_uart_PendForBuffer()".
643  */
644  if(hDevice->pChannelTx->pFreeBuffer->pStartAddress != NULL)
645  {
647  }
648 
649  /* Make sure the DMA transfer size is not too large. */
650  if((bDMA == true) && (nBufSize > DMA_TRANSFER_LIMIT))
651  {
653  }
654 
655 #endif /* ADI_DEBUG */
656 
657  /* Set the start address of the data buffer we are going to submit. */
658  hDevice->pChannelTx->pFreeBuffer->pStartAddress = pBuffer;
659 
660  /* Set the buffer size to the size of the data buffer passed down from the API. */
661  hDevice->pChannelTx->pFreeBuffer->nCount = nBufSize;
662 
663  /* Initialize the buffer index to zero because we will start shifting out
664  the Tx data from the first position of the buffer.
665  */
666  hDevice->pChannelTx->pFreeBuffer->nIndex = 0U;
667 
668  /* Mark the buffer as in use so no other transactions can use it until this one is complete. */
669  hDevice->pChannelTx->pFreeBuffer->bInUse = true;
670 
671  /* Mark the DMA as in use. */
672  hDevice->pChannelTx->pFreeBuffer->bDMA = bDMA;
673 
674  /* Now that this "pFreeBuffer" is no longer free for use, update the
675  "pFreeBuffer" to the other PingPong buffer. Because there are only two
676  buffers in the PingPong structure, this will be the opposite of the one
677  we just submitted. "pFreeBuffer" will only be updated during the process of
678  submitting a buffer or a read/write operation.
679  */
680  hDevice->pChannelTx->pFreeBuffer = hDevice->pChannelTx->pFreeBuffer->pNextBuffer;
681 
682  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE.
683  This will be set back to #ADI_UART_DATA_TRANSFER_MODE_NONE once this
684  transaction is complete. Then, if a buffer is not currently active, set up the
685  interrupts for this transaction. Otherwise if a buffer is currently active,
686  this will be taken care of in the ISR.
687  */
688  if (hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONE)
689  {
690  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING;
691  hDevice->pChannelTx->pfSubmitBuffer(hDevice, hDevice->pChannelTx->pFillBuffer);
692  }
693 
694  return(ADI_UART_SUCCESS);
695  }
696 
699 /*
700  * @brief This is an internal helper function for adi_uart_SubmitTxBuffer(). It sets up the Tx channel DMA
701  or device interrupts for the Tx channel to transmit data.
702  *
703  * @param [in] hDevice Device handle obtained from adi_uart_Open().
704  * @param [in] pBuffer Pointer to buffer from where data will be transmitted.
705  * @param [in] nBufSize Size of the buffer containing the data to be transmitted(in bytes).
706  * @param [in] bDMA Submit the buffer using the DMA.
707 */
708 static void uart_submittxbuffer(
709  ADI_UART_CONST_HANDLE const hDevice,
710  ADI_UART_BUFF_INFO *const pBuffer
711  )
712 {
713  /* If this transmission is using DMA... */
714  if (pBuffer->bDMA)
715  {
716  /* Enable clear source address decrement for TX channel DMA. */
717  pADI_DMA0->SRCADDR_CLR = 1u << (uint32_t)hDevice->pUartInfo->dmaTxChannelNum;
718 
719  /* Enable Tx channel DMA. */
720  pADI_DMA0->EN_SET = 1u << hDevice->pUartInfo->dmaTxChannelNum;
721 
722  /* Enable UART peripheral to generate DMA requests. */
723  pADI_DMA0->RMSK_CLR = 1u << hDevice->pUartInfo->dmaTxChannelNum;
724 
725  /* Set the primary control data structure as the current DMA descriptor. */
726  pADI_DMA0->ALT_CLR = 1u << hDevice->pUartInfo->dmaTxChannelNum;
727 
728  /* Fill in the DMA RAM descriptors */
729  pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum].DMASRCEND = ((uint32_t)pBuffer->pStartAddress + (uint32_t)(pBuffer->nCount - 1u));
730 
731  pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum].DMADSTEND = (uint32_t)&hDevice->pUARTRegs->TX;
732 
733  pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum].DMACDC = ((uint32_t)ADI_DMA_INCR_NONE << DMA_BITP_CTL_DST_INC) |
734  ((uint32_t)ADI_DMA_INCR_1_BYTE << DMA_BITP_CTL_SRC_INC) |
735  (ADI_DMA_WIDTH_1_BYTE << DMA_BITP_CTL_SRC_SIZE) |
736  (0u << DMA_BITP_CTL_R_POWER) |
737  ((pBuffer->nCount - 1u) << DMA_BITP_CTL_N_MINUS_1) |
738  (DMA_ENUM_CTL_CYCLE_CTL_BASIC << DMA_BITP_CTL_CYCLE_CTL);
739  /* Enable UART DMA request interrupt for the Tx channel. */
740  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_EDMAT);
741  }
742  else
743  /* If this transmission is using UART interrupts.. */
744  {
745  /* Enable buffer empty interrupts. */
746  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_ETBEI);
747  }
748 }
749 
785  ADI_UART_HANDLE const hDevice,
786  void *const pBuffer,
787  uint32_t const nBufSize,
788  bool const bDMA
789  )
790 {
791 
792 #ifdef ADI_DEBUG
793  /* Validate the device handle. */
794  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
795  {
796  return(ADI_UART_INVALID_HANDLE);
797  }
798 
799  /* Validate the pointer to the buffer memory. */
800  if(pBuffer == NULL)
801  {
802  return(ADI_UART_INVALID_POINTER);
803  }
804 
805  /* Validate the buffer size. */
806  if(nBufSize == 0U )
807  {
808  return(ADI_UART_FAILED);
809  }
810 
811  /* Autobaud in progress. */
812  if(hDevice->bAutobaudInProgress == true)
813  {
814  return(ADI_UART_DEVICE_IN_USE);
815  }
816 
817  /* Make sure the UART device is configured to operate in the receive direction. */
818  if(ADI_UART_DIR_TRANSMIT == hDevice->eDirection)
819  {
821  }
822 
823  /* Check for the data transfer mode(only allowed in nonblocking mode). */
824  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
825  {
827  }
828 
829  /* Check that there is a free buffer to use for this operation. pFreeBuffer
830  is the next buffer available, so if it is in use we can make the assumption that
831  there are no buffers available. If the start address is not set to NULL, then we
832  can conclude the buffer has not finished being processed because this gets set in
833  adi_uart_pend_for_buffer() and adi_uart_get_buffer().
834  */
835  if(hDevice->pChannelRx->pFreeBuffer->pStartAddress != NULL)
836  {
838  }
839 
840  /* Make sure the DMA transfer size is not too large. */
841  if((bDMA == true) && (nBufSize > DMA_TRANSFER_LIMIT))
842  {
844  }
845 
846 #endif /* ADI_DEBUG */
847 
848  /* Set the start address of the buffer you are going to submit. */
849  hDevice->pChannelRx->pFreeBuffer->pStartAddress = pBuffer;
850 
851  /* Set the size of the buffer. */
852  hDevice->pChannelRx->pFreeBuffer->nCount = nBufSize;
853 
854  /* Initialize the buffer index to 0, because as we receive data it will be put into
855  the buffer starting at the first position.
856  */
857  hDevice->pChannelRx->pFreeBuffer->nIndex = 0U;
858 
859  /* Mark the buffer as in use. */
860  hDevice->pChannelRx->pFreeBuffer->bInUse = true;
861 
862  /* Mark the DMA as in use. */
863  hDevice->pChannelRx->pFreeBuffer->bDMA = bDMA;
864 
865  /* Now that this "pFreeBuffer" is no longer free for use, update the
866  "pFreeBuffer" to the other PingPong buffer. Because there are only two
867  buffers in the PingPong structure, this will be the opposite of the one
868  we just submitted. "pFreeBuffer" will only be updated during the process of
869  submitting a buffer or a read/write operation.
870  */
871  hDevice->pChannelRx->pFreeBuffer = hDevice->pChannelRx->pFreeBuffer->pNextBuffer;
872 
873 
874  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE.
875  This will be set back to #ADI_UART_DATA_TRANSFER_MODE_NONE once this
876  transaction is complete. Then, if a buffer is not currently active, set up the
877  interrupts for this transaction. Otherwise if a buffer is currently active,
878  this will be taken care of in the ISR.
879  */
880  if (hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONE)
881  {
882  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING;
883  hDevice->pChannelRx->pfSubmitBuffer(hDevice, hDevice->pChannelRx->pFillBuffer);
884  }
885 
886  return(ADI_UART_SUCCESS);
887 }
888 
891 /*
892  * @brief This is an internal helper function for adi_uart_SubmitRxBuffer(). It sets up the DMA
893  * or device receive interrupts for the Rx channel to receive data.
894  *
895  * @param [in] hDevice Device handle obtained from adi_uart_Open().
896  * @param [in] pBuffer Pointer to the empty receive buffer.
897  * @param [in] nBufSize Size of the receive buffer(in bytes).
898  * @param [in] bDMA Submit the buffer using the DMA.
899 */
900 static void uart_submitrxbuffer(
901  ADI_UART_CONST_HANDLE const hDevice,
902  ADI_UART_BUFF_INFO *const pBuffer
903  )
904 {
905 
906 
907  /* If this transaction is using the DMA.. */
908  if (pBuffer->bDMA)
909  {
910  /* Enable source address decrement for RX DMA channel. */
911  pADI_DMA0->DSTADDR_CLR = 1u << (uint32_t)hDevice->pUartInfo->dmaRxChannelNum;
912 
913  /* Enable Rx DMA channel. */
914  pADI_DMA0->EN_SET = 1u << hDevice->pUartInfo->dmaRxChannelNum;
915 
916  /* Enable UART peripheral to generate DMA requests. */
917  pADI_DMA0->RMSK_CLR = 1u << hDevice->pUartInfo->dmaRxChannelNum;
918 
919  /* Set the primary data structure as the current DMA descriptor. */
920  pADI_DMA0->ALT_CLR = 1u << hDevice->pUartInfo->dmaRxChannelNum;
921 
922  /* Fill in the DMA RAM descriptors. */
923  pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum].DMASRCEND = (uint32_t)&hDevice->pUARTRegs->RX;
924 
925  pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum].DMADSTEND = ((uint32_t)pBuffer->pStartAddress + (uint32_t)(pBuffer->nCount - 1u));
926 
927  pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum].DMACDC = (uint32_t)(ADI_DMA_INCR_1_BYTE << DMA_BITP_CTL_DST_INC) |
928  (uint32_t)(ADI_DMA_INCR_NONE << DMA_BITP_CTL_SRC_INC) |
929  (ADI_DMA_WIDTH_1_BYTE << DMA_BITP_CTL_SRC_SIZE) |
930  (0u << DMA_BITP_CTL_R_POWER) |
931  ((pBuffer->nCount - 1u) << DMA_BITP_CTL_N_MINUS_1) |
932  (DMA_ENUM_CTL_CYCLE_CTL_BASIC << DMA_BITP_CTL_CYCLE_CTL);
933  /* Enable UART receive DMA requests. */
934  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_EDMAR);
935  }
936  /* If this transaction is using UART interrupts.. */
937  else
938  {
939  /* Enable buffer full interrupt. */
940  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_ERBFI);
941  }
942 }
943 
971  ADI_UART_HANDLE const hDevice,
972  void **const ppBuffer,
973  uint32_t *pHwError
974  )
975 
976 {
977 
978 #ifdef ADI_DEBUG
979  /* Validate the device handle. */
980  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
981  {
982  return(ADI_UART_INVALID_HANDLE);
983  }
984 
985  /* Validate that this buffer has actually been submitted. */
986  if(hDevice->pChannelTx->pActiveBuffer->pStartAddress == NULL)
987  {
989  }
990 
991  /* This function is allowed to be called when the channel is operating in NONBLOCKING mode. */
992  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
993  {
995  }
996 #endif /* ADI_DEBUG */
997 
998  /* Blocking call to get the submitted buffer */
999  return(uart_getbuffer(hDevice, hDevice->pChannelTx, ppBuffer, pHwError));
1000 }
1001 
1002 
1003 
1029  ADI_UART_HANDLE const hDevice,
1030  void **const ppBuffer,
1031  uint32_t *pHwError
1032  )
1033 
1034 {
1035 
1036 #ifdef ADI_DEBUG
1037  /* Validate the device handle. */
1038  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1039  {
1040  return(ADI_UART_INVALID_HANDLE);
1041  }
1042 
1043  /* Validate that this buffer has actually been submitted. */
1044  if(hDevice->pChannelRx->pActiveBuffer->pStartAddress == NULL)
1045  {
1047  }
1048 
1049  /* This function is only allowed to be called when the channel is operating in NONBLOCKING mode. */
1050  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
1051  {
1053  }
1054 #endif /* ADI_DEBUG */
1055 
1056  /* Blocking call to get the full Rx Buffer */
1057  return(uart_getbuffer(hDevice, hDevice->pChannelRx, ppBuffer, pHwError));
1058 }
1059 
1062 /*
1063  * @brief This is an internal helper function for adi_uart_GetRxBuffer() and adi_uart_GetTxBuffer().
1064  * It blocks until until the completion of the data transaction.
1065  *
1066  * @param [in] hDevice Device handle obtained from adi_uart_Open().
1067  * @param [in] pChannel Pointer to UART channel data structure.
1068  * @param [out] ppBuffer Contains the address of the buffer passed down from the API.
1069  * @param [out] pHwError Pointer to an integer that correlates with #ADI_UART_HW_ERRORS, containg the hardware status.
1070  * If there is no hardware event, this will be 0.
1071  *
1072  * @return Status
1073  * - #ADI_UART_SUCCESS Successfully got buffer.
1074  * - #ADI_UART_HW_ERROR_DETECTED Hardware error(s) detected. "pHwError" can be checked for the specific error code(s).
1075  *
1076 */
1077 static ADI_UART_RESULT uart_getbuffer(
1078  ADI_UART_HANDLE hDevice,
1079  ADI_UART_DATA_CHANNEL *pChannel,
1080  void **ppBuffer,
1081  uint32_t *pHwError
1082  )
1083 {
1084  /* Set ppBuffer to NULL in case there is an error. */
1085  *ppBuffer = NULL;
1086 
1087  /* Wait until the peripheral has finished processing the buffer. */
1088  SEM_PEND(pChannel,ADI_UART_FAILED);
1089 
1090  /* Save the address of the buffer that has just been processed, so it can be
1091  returned back to the API.
1092  */
1093  *ppBuffer = pChannel->pActiveBuffer->pStartAddress;
1094 
1095  /* Reinitialize the start address to NULL so this buffer can be used for a new transaction. */
1096  pChannel->pActiveBuffer->pStartAddress = NULL;
1097 
1098  /* Now that the desired data has either been transmitted or received, this buffer is no longer
1099  in use. We can update "pActiveBuffer" to point to the next buffer that will become or is already
1100  active.
1101  */
1102  pChannel->pActiveBuffer = pChannel->pActiveBuffer->pNextBuffer;
1103 
1104  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
1105  This will only be done if there are no other active buffers in flight to avoid disrupting an active transfer.
1106  */
1107  if(pChannel->pActiveBuffer->pStartAddress == NULL)
1108  {
1109  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
1110  }
1111 
1112  /* If there are hardware errors and no callback, then return failure. */
1113  if(hDevice->nHwError != 0u)
1114  {
1115  /* Save the hardware error detected. This will be passed back to the API. */
1116  *pHwError = hDevice->nHwError;
1117 
1118  /* Clear any hardware errors detected. */
1119  hDevice->nHwError = 0u;
1120 
1122  }
1123  else
1124  {
1125  return(ADI_UART_SUCCESS);
1126  }
1127 }
1128 
1167  ADI_UART_HANDLE const hDevice,
1168  void *const pBuffer,
1169  uint32_t const nBufSize,
1170  bool const bDMA,
1171  uint32_t *pHwError
1172  )
1173 {
1174 
1175 #ifdef ADI_DEBUG
1176  /* Validate the given handle. */
1177  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1178  {
1179  return(ADI_UART_INVALID_HANDLE);
1180  }
1181 
1182  /* Validate the pointer to the buffer memory. */
1183  if(pBuffer == NULL)
1184  {
1185  return(ADI_UART_INVALID_POINTER);
1186  }
1187 
1188  /* Validate the buffer size. */
1189  if(nBufSize == 0U )
1190  {
1191  return(ADI_UART_FAILED);
1192  }
1193 
1194  /* Autobaud in progress. */
1195  if(hDevice->bAutobaudInProgress == true)
1196  {
1197  return(ADI_UART_DEVICE_IN_USE);
1198  }
1199 
1200  /* Make sure we are transmitting. */
1201  if(ADI_UART_DIR_RECEIVE == hDevice->eDirection)
1202  {
1204  }
1205 
1206  /* Check for the data transfer mode (only allowed in blocking mode). */
1207  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING)
1208  {
1210  }
1211 
1212  /* Check that there is a free buffer to use for this transmit operation. "pFreeBuffer"
1213  is the next buffer available, so if it is in use we can make the assumption that
1214  there are no buffers available. The start address is set to NULL once the buffer
1215  has been processed.
1216  */
1217  if(hDevice->pChannelTx->pFreeBuffer->pStartAddress != NULL)
1218  {
1220  }
1221 
1222  /* Make sure the DMA transfer size is not too large. */
1223  if((bDMA == true) && (nBufSize > DMA_TRANSFER_LIMIT))
1224  {
1226  }
1227 
1228 #endif /* ADI_DEBUG */
1229 
1230  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE. */
1231  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_BLOCKING;
1232 
1233  /* Set the start address of the data buffer we are going to submit. */
1234  hDevice->pChannelTx->pFreeBuffer->pStartAddress = pBuffer;
1235 
1236  /* Set the buffer size to the size of the data buffer passed down from the API. */
1237  hDevice->pChannelTx->pFreeBuffer->nCount = nBufSize;
1238 
1239  /* Initialize the buffer index to zero because we will start shifting out
1240  the Tx data from the first position of the buffer.
1241  */
1242  hDevice->pChannelTx->pFreeBuffer->nIndex = 0U;
1243 
1244  /* Mark the buffer as in use so no other transactions can use it until this one is complete. */
1245  hDevice->pChannelTx->pFreeBuffer->bInUse = true;
1246 
1247  /* Mark the DMA as in use. */
1248  hDevice->pChannelTx->pFreeBuffer->bDMA = bDMA;
1249 
1250  /* Now that this "pFreeBuffer" is no longer free for use, update the
1251  "pFreeBuffer" to the other PingPong buffer. Because there are only two
1252  buffers in the PingPong structure, this will be the opposite of the one
1253  we just submitted. "pFreeBuffer" will only be updated during the process of
1254  submitting a buffer or a read/write operation.
1255  */
1256  hDevice->pChannelTx->pFreeBuffer = hDevice->pChannelTx->pFreeBuffer->pNextBuffer;
1257 
1258  hDevice->pChannelTx->pfSubmitBuffer(hDevice, hDevice->pChannelTx->pFillBuffer);
1259 
1260  /* Block for the active buffer to complete. */
1261  return(uart_PendForBuffer(hDevice, hDevice->pChannelTx, pHwError));
1262 }
1263 
1299  ADI_UART_HANDLE const hDevice,
1300  void *const pBuffer,
1301  uint32_t const nBufSize,
1302  bool const bDMA,
1303  uint32_t *pHwError
1304  )
1305 {
1306 
1307 #ifdef ADI_DEBUG
1308  /* Validate the given handle. */
1309  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1310  {
1311  return(ADI_UART_INVALID_HANDLE);
1312  }
1313 
1314  /* Validate the pointer to the buffer memory. */
1315  if(pBuffer == NULL)
1316  {
1317  return(ADI_UART_INVALID_POINTER);
1318  }
1319 
1320  /* Validate the buffer size. */
1321  if(nBufSize == 0U )
1322  {
1323  return(ADI_UART_FAILED);
1324  }
1325 
1326  /* Autobaud in progress. */
1327  if(hDevice->bAutobaudInProgress == true)
1328  {
1329  return(ADI_UART_DEVICE_IN_USE);
1330  }
1331 
1332  /* Make sure the UART device is configured to operate in the receive direction. */
1333  if(ADI_UART_DIR_TRANSMIT == hDevice->eDirection)
1334  {
1336  }
1337 
1338  /* Check for the data transfer mode(only allowed in blocking mode).*/
1339  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING)
1340  {
1342  }
1343 
1344  /* Check that there is a free buffer to use for this receive operation. "pFreeBuffer"
1345  is the next buffer available, so if it is in use we can make the assumption that
1346  there are no buffers available. The start address gets set to NULL once the buffer
1347  processing has completed.
1348  */
1349  if(hDevice->pChannelRx->pFreeBuffer->pStartAddress != NULL)
1350  {
1352  }
1353 
1354  /* Make sure the DMA transfer size is not too large. */
1355  if((bDMA == true) && (nBufSize > DMA_TRANSFER_LIMIT))
1356  {
1358  }
1359 
1360 #endif /* ADI_DEBUG */
1361 
1362  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE.
1363  This will be set back to #ADI_UART_DATA_TRANSFER_MODE_NONE once this
1364  transaction is complete.
1365  */
1366  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_BLOCKING;
1367 
1368  /* Set the start address of the buffer you are going to submit. */
1369  hDevice->pChannelRx->pFreeBuffer->pStartAddress = pBuffer;
1370 
1371  /* Set the size of the buffer. */
1372  hDevice->pChannelRx->pFreeBuffer->nCount = nBufSize;
1373 
1374  /* Initialize the buffer index to 0, because as we receive data it will be put into
1375  the buffer starting at the first position.
1376  */
1377  hDevice->pChannelRx->pFreeBuffer->nIndex = 0U;
1378 
1379  /* Mark the buffer as in use. */
1380  hDevice->pChannelRx->pFreeBuffer->bInUse = true;
1381 
1382  /* Mark the DMA as in use. */
1383  hDevice->pChannelRx->pFreeBuffer->bDMA = bDMA;
1384 
1385 
1386  /* Now that this "pFreeBuffer" is no longer free for use, update the
1387  "pFreeBuffer" to the other PingPong buffer. Because there are only two
1388  buffers in the PingPong structure, this will be the opposite of the one
1389  we just submitted. "pFreeBuffer" will only be updated during the process of
1390  submitting a buffer or a read/write operation.
1391  */
1392  hDevice->pChannelRx->pFreeBuffer = hDevice->pChannelRx->pFreeBuffer->pNextBuffer;
1393 
1394  hDevice->pChannelRx->pfSubmitBuffer(hDevice, hDevice->pChannelRx->pFillBuffer);
1395 
1396  /* Block for the active buffer to complete. */
1397  return(uart_PendForBuffer(hDevice, hDevice->pChannelRx, pHwError));
1398 }
1399 
1402 /*
1403  * @brief Pends for data transaction to complete. Buffer gets returned to API.
1404  *
1405  * @param [in] hDevice Device handle obtained from adi_uart_Open().
1406  * @param [in] pChannel Pointer to UART channel data structure.
1407  * @param [out] pBuffer Address of buffer on which data transfer being carried out.
1408  * @param [out] pHwError Pointer to an integer that correlates with #ADI_UART_HW_ERRORS, containg the hardware status.
1409  * If there is no hardware event, this will be 0.
1410  *
1411  * @return Status
1412  * - #ADI_UART_SUCCESS Successfully got buffer.
1413  * - #ADI_UART_HW_ERROR_DETECTED Hardware error(s) detected. "pHwError" can be checked for the specific error code(s).
1414  *
1415 */
1416 static ADI_UART_RESULT uart_PendForBuffer(
1417  ADI_UART_HANDLE const hDevice,
1418  ADI_UART_DATA_CHANNEL *pChannel,
1419  uint32_t *pHwError
1420  )
1421 {
1422 
1423  /* Wait until the peripheral has finished processing the buffer. */
1424  SEM_PEND(pChannel,ADI_UART_FAILED);
1425 
1426  /* Reinitialize the start address to NULL so this buffer can be used for a new transaction. */
1427  pChannel->pActiveBuffer->pStartAddress = NULL;
1428 
1429  /* Now that the desired data has either been transmitted or received, this buffer is no longer
1430  in use. We can update "pActiveBuffer" to point to the next buffer that will become or is already
1431  active. This will only be updated in places where transactions are completed,
1432  such as uart_PendForBuffer() and uart_GetBuffer().
1433  */
1434  pChannel->pActiveBuffer = pChannel->pActiveBuffer->pNextBuffer;
1435 
1436  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
1437  Only if there are no active buffers.
1438  */
1439  if(pChannel->pActiveBuffer->pStartAddress == NULL)
1440  {
1441  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
1442  }
1443 
1444  /* If there are hardware errors and no callback, then return failure. */
1445  if(hDevice->nHwError != 0u)
1446  {
1447  /* Save the hardware error detected. This will be passed back to the API. */
1448  *pHwError = hDevice->nHwError;
1449 
1450  /* Clear any hardware errors detected. */
1451  hDevice->nHwError = 0u;
1452 
1454  }
1455  else
1456  {
1457  return(ADI_UART_SUCCESS);
1458  }
1459 
1460 }
1482  ADI_UART_HANDLE const hDevice,
1483  bool *const pbAvailable
1484  )
1485 {
1486 
1487 #ifdef ADI_DEBUG
1488  /* Validate the given handle. */
1489  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1490  {
1491  return(ADI_UART_INVALID_HANDLE);
1492  }
1493 
1494  /* This function is only allowed to be called when the channel is operating in NONBLOCKING mode. */
1495  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
1496  {
1498  }
1499 #endif /* ADI_DEBUG */
1500 
1501  /* Initialize to "false" in case of an error. */
1502  *pbAvailable = false;
1503 
1504  /* Make sure the buffer has not already been processed. This would mean that there are
1505  currently no active buffers. This is only updated in adi_uart_GetBuffer(), which is
1506  called once a transaction has completed.
1507  */
1508  if (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)
1509  {
1510  /* If the buffer has reached the interrupt handler, "bInUse" will be
1511  updated so we know that the buffer has become available.
1512  */
1513  if (hDevice->pChannelTx->pActiveBuffer->bInUse == false)
1514  {
1515  *pbAvailable = true;
1516  }
1517  }
1518  return(ADI_UART_SUCCESS);
1519 }
1520 
1538  ADI_UART_HANDLE const hDevice,
1539  bool *const pbAvailable
1540  )
1541 {
1542 
1543 #ifdef ADI_DEBUG
1544  /* Validate the given handle. */
1545  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1546  {
1547  return(ADI_UART_INVALID_HANDLE);
1548  }
1549 
1550  /* This function is only allowed to be called when the channel is operating in NONBLOCKING mode. */
1551  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
1552  {
1554  }
1555 #endif /* ADI_DEBUG */
1556 
1557  /* Initialize to "false" in case of an error. */
1558  *pbAvailable = false;
1559 
1560  /* Make sure the buffer has not already been processed. This would mean that there are
1561  currently no active buffers. This is only updated in adi_uart_GetBuffer(), which is
1562  called once a transaction has completed.
1563  */
1564  if(hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)
1565  {
1566  /* If the buffer has reached the interrupt handler, "bInUse" will be
1567  updated so we know that the buffer has become available.
1568  */
1569  if (hDevice->pChannelRx->pActiveBuffer->bInUse == false)
1570  {
1571  *pbAvailable = true;
1572  }
1573  }
1574  return(ADI_UART_SUCCESS);
1575 }
1576 
1597  ADI_UART_HANDLE const hDevice,
1598  bool *const pbComplete
1599  )
1600 {
1601 #ifdef ADI_DEBUG
1602  /* Validate the given handle. */
1603  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1604  {
1605  return(ADI_UART_INVALID_HANDLE);
1606  }
1607 #endif /* ADI_DEBUG */
1608 
1609  /* Initialize to false. */
1610  *pbComplete = false;
1611 
1612  /* If the register is empty, set the return variable to "true".
1613  This register is empty, when the value becomes a 1.
1614  */
1615  if((hDevice->pUARTRegs->LSR & BITM_UART_LSR_TEMT) == BITM_UART_LSR_TEMT)
1616  {
1617  *pbComplete = true;
1618  }
1619  return(ADI_UART_SUCCESS);
1620 }
1621 
1622 
1639  ADI_UART_HANDLE const hDevice,
1640  const ADI_CALLBACK pfCallback,
1641  void *const pCBParam
1642  )
1643 {
1644 
1645 #ifdef ADI_DEBUG
1646  /* Validate the given handle. */
1647  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1648  {
1649  return(ADI_UART_INVALID_HANDLE);
1650  }
1651 
1652  /* Make sure there are no active buffers on any active channel and autobaud is not in progress. */
1653  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
1654  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)) ||
1655  (hDevice->bAutobaudInProgress == true))
1656  {
1657  return(ADI_UART_DEVICE_IN_USE);
1658  }
1659 #endif /* ADI_DEBUG */
1660 
1661  /* Set the device callback. */
1662  hDevice->pfCallback = pfCallback;
1663 
1664  /* Set the callback parameter. */
1665  hDevice->pCBParam = pCBParam;
1666 
1667  return(ADI_UART_SUCCESS);
1668 }
1669 
1670 
1690  ADI_UART_HANDLE const hDevice,
1691  ADI_UART_PARITY const eParity,
1692  ADI_UART_STOPBITS const eStopBits,
1693  ADI_UART_WORDLEN const eWordLength
1694  )
1695 {
1696 #ifdef ADI_DEBUG
1697  /* Validate the given handle. */
1698  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1699  {
1700  return(ADI_UART_INVALID_HANDLE);
1701  }
1702 
1703  /* Make sure there are no active buffers on any active channel and autobaud is not in progress. */
1704  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
1705  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)) ||
1706  (hDevice->bAutobaudInProgress == true))
1707  {
1708  return(ADI_UART_DEVICE_IN_USE);
1709  }
1710 #endif /* ADI_DEBUG */
1711 
1712  /* Clear all the fields. */
1713  uint16_t nDataCfg = hDevice->pUARTRegs->LCR & (uint16_t)(~(BITM_UART_LCR_WLS |BITM_UART_LCR_STOP |BITM_UART_LCR_PEN));
1714 
1715  /* Construct the configuration word. */
1716  nDataCfg |= (uint16_t)(((uint16_t)((uint16_t)eWordLength |(uint16_t)eStopBits) |(uint16_t)eParity));
1717 
1718  /* Write to the register */
1719  hDevice->pUARTRegs->LCR = nDataCfg;
1720 
1721  /* Return Success */
1722  return(ADI_UART_SUCCESS);
1723 }
1724 
1752  ADI_UART_HANDLE const hDevice,
1753  uint16_t const nDivC,
1754  uint8_t const nDivM,
1755  uint16_t const nDivN,
1756  uint8_t const nOSR
1757  )
1758 {
1759 #ifdef ADI_DEBUG
1760  /* Validate the given handle */
1761  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1762  {
1763  return(ADI_UART_INVALID_HANDLE);
1764  }
1765 
1766  /* Make sure there are no active buffers on any active channel. */
1767  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
1768  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)))
1769  {
1770  return(ADI_UART_DEVICE_IN_USE);
1771  }
1772 
1773  /* Check if the given baudrate is valid */
1774  if( (nDivM < 1u) || (nDivM > 3u)|| (nDivN > 2047u ) || (nOSR > 3u))
1775  {
1777  }
1778 
1779 #endif /* ADI_DEBUG */
1780 
1781  /* Write back the register contents for baudrate detection in the hardware. */
1782  hDevice->pUARTRegs->DIV = nDivC;
1783  hDevice->pUARTRegs->FBR = (uint16_t)((uint16_t)nDivN | (uint16_t)((uint16_t)nDivM <<BITP_UART_FBR_DIVM)) | (uint16_t)BITM_UART_FBR_FBEN;
1784  hDevice->pUARTRegs->LCR2 = nOSR;
1785 
1786  return(ADI_UART_SUCCESS);
1787 }
1788 
1789 
1810  ADI_UART_HANDLE const hDevice,
1811  uint32_t *pnBaudRate,
1812  uint32_t *pAutobaudError
1813  )
1814 {
1815 
1816 #ifdef ADI_DEBUG
1817  /* Validate the given handle. */
1818  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1819  {
1820  return(ADI_UART_INVALID_HANDLE);
1821  }
1822 
1823  /* Validate pointers. */
1824  if(pnBaudRate == NULL)
1825  {
1826  return(ADI_UART_INVALID_POINTER);
1827  }
1828 
1829 #endif /* ADI_DEBUG */
1830 
1831  /* If an error occured during autobaud this value will be set to a
1832  non-zero value. The specific error can be found by checking against
1833  #ADI_UART_EVENT.
1834  */
1835  if(hDevice->nAutobaudError != 0u)
1836  {
1837  /* Save the autobaud error to pass back to the API.*/
1838  *pAutobaudError = hDevice->nAutobaudError;
1839 
1840  /* Clear the autobaud errors found. */
1841  hDevice->nAutobaudError = 0u;
1842 
1844  }
1845 
1846  /* Return the baudrate. If this is 0, then autobaud has not completed. */
1847  *pnBaudRate = hDevice->nBaudRate;
1848 
1849  return(ADI_UART_SUCCESS);
1850 }
1851 
1852 
1879  ADI_UART_HANDLE const hDevice,
1880  bool const bEnable,
1881  bool const bAutobaudCallbackMode
1882  )
1883 {
1884 
1885 #ifdef ADI_DEBUG
1886  /* Validate the given handle */
1887  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1888  {
1889  return(ADI_UART_INVALID_HANDLE);
1890  }
1891 
1892  /* Make sure there are no active buffers on any active channel and autobaud is not in progress. */
1893  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
1894  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)))
1895  {
1896  return(ADI_UART_DEVICE_IN_USE);
1897  }
1898 
1899 #endif /* ADI_DEBUG */
1900 
1901  if(bEnable)
1902  {
1903  /* Enable Autobaud, timeout interrupt and done interrupt in the autobaud control register.
1904  Set the starting edge trigger to the second edge. Set the ending edge count to
1905  the fourth edge, for the carrige return key character (0xD).
1906  */
1907  hDevice->pUARTRegs->ACR |=(BITM_UART_ACR_ABE | BITM_UART_ACR_DNIEN | BITM_UART_ACR_TOIEN |(1u << 4u) | (3u << 8u));
1908 
1909  /* Initialize device baudrate to 0. This will be set once autobaud is complete. */
1910  hDevice->nBaudRate = 0u;
1911 
1912  /* Change the state to indicate autobaud is in progress. */
1913  hDevice->bAutobaudInProgress = true;
1914 
1915  /* Set the callback mode for autobaud based on the user input. */
1916  hDevice->bAutobaudCallbackMode = bAutobaudCallbackMode;
1917  }
1918  else
1919  {
1920  /* Change the state to indicate autobaud is not in progress. */
1921  hDevice->bAutobaudInProgress = false;
1922 
1923  /* Disable Autobaud, timeout interrupt and done interrupt in the autobaud control register. */
1924  hDevice->pUARTRegs->ACR |= (uint16_t)(~(uint32_t)BITM_UART_ACR_ABE | ~(uint32_t)BITM_UART_ACR_DNIEN | ~(uint32_t)BITM_UART_ACR_TOIEN);
1925 
1926  /* Initialize device baudrate to 0. */
1927  hDevice->nBaudRate = 0u;
1928  }
1929 
1930  return ADI_UART_SUCCESS;
1931 }
1932 
1951  ADI_UART_HANDLE const hDevice,
1952  bool const bEnable
1953  )
1954 {
1955 
1956 #ifdef ADI_DEBUG
1957  /* Validate the given handle. */
1958  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1959  {
1960  return(ADI_UART_INVALID_HANDLE);
1961  }
1962 #endif /* ADI_DEBUG */
1963 
1964  if(bEnable == true)
1965  {
1966  /* Set the force break bit. */
1967  hDevice->pUARTRegs->LCR |= BITM_UART_LCR_BRK;
1968  }
1969  else
1970  {
1971  /* Clear the force break bit. */
1972  hDevice->pUARTRegs->LCR &= (uint16_t)~(BITM_UART_LCR_BRK);
1973  }
1974 
1975  return ADI_UART_SUCCESS;
1976 }
1977 
1990  ADI_UART_HANDLE const hDevice,
1991  bool const bEnable
1992  )
1993 {
1994 
1995 #ifdef ADI_DEBUG
1996  /* Validate the given handle. */
1997  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1998  {
1999  return(ADI_UART_INVALID_HANDLE);
2000  }
2001 #endif /* ADI_DEBUG */
2002 
2003  if(true == bEnable)
2004  {
2005  /* Enable loopback. */
2006  hDevice->pUARTRegs->MCR |= (BITM_UART_MCR_LOOPBACK);
2007  }
2008  else
2009  {
2010  /* Disable loopback. */
2011  hDevice->pUARTRegs->MCR &= (uint16_t)~(BITM_UART_MCR_LOOPBACK);
2012  }
2013  return(ADI_UART_SUCCESS);
2014 }
2015 
2029  ADI_UART_HANDLE const hDevice,
2030  ADI_UART_TRIG_LEVEL const eTriglevel
2031  )
2032 {
2033 #ifdef ADI_DEBUG
2034  /* Validate the given handle. */
2035  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2036  {
2037  return(ADI_UART_INVALID_HANDLE);
2038  }
2039 #endif /* ADI_DEBUG */
2040 
2041  /* Clear existing FIFO trigger level. */
2042  hDevice->pUARTRegs->FCR &= (uint16_t)~BITM_UART_FCR_RFTRIG;
2043 
2044  /* Set the FIFO trigger level. */
2045  hDevice->pUARTRegs->FCR |= (uint16_t)eTriglevel;
2046 
2047  /* Update the internal structure */
2048  hDevice->nRxFifoTrig = sFifoTriggers[eTriglevel >> BITP_UART_FCR_RFTRIG];
2049 
2050  return(ADI_UART_SUCCESS);
2051 }
2064  ADI_UART_HANDLE const hDevice,
2065  bool const bEnable
2066  )
2067 {
2068 
2069 #ifdef ADI_DEBUG
2070  /* Validate the given handle. */
2071  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2072  {
2073  return(ADI_UART_INVALID_HANDLE);
2074  }
2075 #endif /* ADI_DEBUG */
2076 
2077  if(bEnable == true)
2078  {
2079  /* Enable TX/RX FIFO. */
2080  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_FIFOEN;
2081  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_ERBFI);
2082 
2083  hDevice->bRxFifoEn = true;
2084 
2085  }
2086  else
2087  {
2088  /* Disable TX/RX FIFO. */
2089  hDevice->pUARTRegs->FCR &= (uint16_t)~(BITM_UART_FCR_FIFOEN);
2090 
2091  hDevice->bRxFifoEn = false;
2092  }
2093 
2094  return ADI_UART_SUCCESS;
2095 }
2096 
2109  ADI_UART_CONST_HANDLE const hDevice
2110  )
2111 {
2112 
2113 #ifdef ADI_DEBUG
2114  /* Validate the given handle. */
2115  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2116  {
2117  return(ADI_UART_INVALID_HANDLE);
2118  }
2119 #endif /* ADI_DEBUG */
2120 
2121  /* Flush the Tx FIFO. */
2122  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_TFCLR;
2123 
2124  return(ADI_UART_SUCCESS);
2125 }
2126 
2139  ADI_UART_CONST_HANDLE const hDevice
2140  )
2141 {
2142 
2143 #ifdef ADI_DEBUG
2144  /* Validate the given handle. */
2145  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2146  {
2147  return(ADI_UART_INVALID_HANDLE);
2148  }
2149 #endif /* ADI_DEBUG */
2150 
2151  /* Flush RX FIFO. */
2152  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_RFCLR;
2153 
2154  return ADI_UART_SUCCESS;
2155 }
2156 
2171  ADI_UART_CONST_HANDLE const hDevice
2172  )
2173 {
2174 
2175 #ifdef ADI_DEBUG
2176  /* Validate the given handle. */
2177  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2178  {
2179  return(ADI_UART_INVALID_HANDLE);
2180  }
2181 #endif /* ADI_DEBUG */
2182 
2183  /* Disable receive interrupts in PIO mode as well as DMA mode. */
2184  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ERBFI | BITM_UART_IEN_EDMAR);
2185 
2186  /* Clear any data in the Rx Fifo. */
2187  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_RFCLR;
2188 
2189  /* Reset the data transfer mode. */
2190  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
2191 
2192  /* Reset the buffers to 0. */
2193  memset(hDevice->pChannelRx->PingPong,0, sizeof (hDevice->pChannelRx->PingPong));
2194 
2195  hDevice->pChannelRx->PingPong[0].pNextBuffer = &hDevice->pChannelRx->PingPong[1];
2196  hDevice->pChannelRx->PingPong[1].pNextBuffer = &hDevice->pChannelRx->PingPong[0];
2197 
2198  /* Reset the buffer pointers. */
2199  hDevice->pChannelRx->pActiveBuffer = &hDevice->pChannelRx->PingPong[0];
2200  hDevice->pChannelRx->pFreeBuffer = &hDevice->pChannelRx->PingPong[0];
2201  hDevice->pChannelRx->pFillBuffer = &hDevice->pChannelRx->PingPong[0];
2202 
2203  /* Dummy read to flush the RX register. */
2204  hDevice->pUARTRegs->RX;
2205 
2206  return(ADI_UART_SUCCESS);
2207 }
2208 
2222 {
2223 
2224 #ifdef ADI_DEBUG
2225  /* Validate the given handle. */
2226  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2227  {
2228  return(ADI_UART_INVALID_HANDLE);
2229  }
2230 #endif /* ADI_DEBUG */
2231 
2232  /* Disable transmit interrupts in PIO mode as well as DMA mode. */
2233  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ETBEI | BITM_UART_IEN_EDMAT);
2234 
2235  /* Clear any data in the Rx Fifo. */
2236  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_TFCLR;
2237 
2238  /* Reset the buffers to 0. */
2239  memset(hDevice->pChannelTx->PingPong,0, sizeof (hDevice->pChannelTx->PingPong));
2240 
2241  hDevice->pChannelTx->PingPong[0].pNextBuffer = &hDevice->pChannelTx->PingPong[1];
2242  hDevice->pChannelTx->PingPong[1].pNextBuffer = &hDevice->pChannelTx->PingPong[0];
2243 
2244  /* Reset the buffer pointers. */
2245  hDevice->pChannelTx->pActiveBuffer = &hDevice->pChannelTx->PingPong[0];
2246  hDevice->pChannelTx->pFreeBuffer = &hDevice->pChannelTx->PingPong[0];
2247  hDevice->pChannelTx->pFillBuffer = &hDevice->pChannelTx->PingPong[0];
2248 
2249  return(ADI_UART_SUCCESS);
2250 }
2251 
2252 
2255 void UART0_Int_Handler(void)
2256 {
2257  ISR_PROLOG();
2258  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)uart_device_info[0].hDevice;
2259  Common_Uart_Interrupt_Handler(hDevice);
2260 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2262 #endif
2263  ISR_EPILOG();
2264  return;
2265 }
2266 
2267 #if defined (__ADUCM4x50__)
2268 
2269 void UART1_Int_Handler(void)
2270 {
2271  ISR_PROLOG();
2272  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)uart_device_info[1].hDevice;
2273  Common_Uart_Interrupt_Handler(hDevice);
2274 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2276 #endif
2277  ISR_EPILOG();
2278  return;
2279 }
2280 #endif
2281 
2282 static void Common_Uart_Interrupt_Handler(ADI_UART_HANDLE hDevice)
2283 {
2284  switch(hDevice->pUARTRegs->IIR & BITM_UART_IIR_STAT )
2285  {
2286  /* Tx buffer empty interrupt. This means that the data has successfully left the holding register and is
2287  now in transmit shift register or has completed its transfer.
2288  */
2289  case ENUM_UART_IIR_STAT_ETBEI:
2290  uart_TxDataHandler(hDevice);
2291  break;
2292 
2293  /* Rx buffer FIFO timeout interrupt. This means that we have data in the RX FIFO
2294  but there is not enough data to trigger an interrupt so we will process this data here.
2295  */
2296  case ENUM_UART_IIR_STAT_RFTOI:
2297  /* Extract as many bytes in Rx FIFO as possible.
2298  * subsequent timeout int will take care of remaining bytes if needed. */
2299  uart_RxDataHandler(hDevice, hDevice->pUARTRegs->RFC);
2300  break;
2301 
2302  /* Rx buffer full interrupt. This means that the RX buffer has finished receiving data. */
2303  case ENUM_UART_IIR_STAT_ERBFI:
2304  /* Extract the amount of data based on the size of the trigger */
2305  uart_RxDataHandler(hDevice, hDevice->nRxFifoTrig);
2306  break;
2307 
2308  /* Line status interrupt. */
2309  case ENUM_UART_IIR_STAT_RLSI:
2310  {
2311  /* Initialze the line status event to 0. */
2312  uint32_t nEvent = 0u;
2313 
2314  /* Get the interrupts status. */
2315  uint16_t nStatus = hDevice->pUARTRegs->LSR;
2316 
2317  /* If a break signal is detected.. */
2318  if((BITM_UART_LSR_BI & nStatus) == BITM_UART_LSR_BI)
2319  {
2320  /* Dummy read to flush the RX register. We do this because
2321  we do not actaully want to do anything with this data as it
2322  is only a break indicator. */
2323  hDevice->pUARTRegs->RX;
2324 
2325  /* Set the event to a break interrupt. */
2326  nEvent = (uint32_t)ADI_UART_BREAK_INTERRUPT;
2327  }
2328 
2329  /* Ignore the framing error if the break is asserted.
2330  We do this because a break can trigger a false framing error.
2331  */
2332  else if((BITM_UART_LSR_FE & nStatus) == BITM_UART_LSR_FE)
2333  {
2334  /* Set the event to show a framing error has been detected. */
2335  nEvent |= (uint32_t)ADI_UART_HW_ERR_FRAMING;
2336  }
2337  else
2338  {
2339  /* Do nothing. This is required for MISRA. */
2340  }
2341 
2342  if((BITM_UART_LSR_PE & nStatus) == BITM_UART_LSR_PE)
2343  {
2344  /* Set the event to show a parity error has been detected. */
2345  nEvent |= (uint32_t)ADI_UART_HW_ERR_PARITY;
2346  }
2347  if((BITM_UART_LSR_OE & nStatus) == BITM_UART_LSR_OE)
2348  {
2349  /* Set the event to show a hardware overrun error has been detected, meaning receive data has
2350  been overwritten.
2351  */
2352  nEvent |= (uint32_t)ADI_UART_HW_ERR_OVERRUN;
2353  }
2354 
2355  /* If there was an event and autobaud is not in progress, notify the API. */
2356  if((nEvent != 0u) && (hDevice->bAutobaudInProgress == false))
2357  {
2358  /* Set the UART device hw error bit field. This will allow us to return the
2359  specific failure to the application once we return from this ISR.
2360  */
2361  hDevice->nHwError |= nEvent;
2362  uart_ManageProcessedBuffer(hDevice, hDevice->pChannelRx, ADI_UART_EVENT_HW_ERROR_DETECTED);
2363  }
2364  break;
2365  }
2366 
2367  /* If there was a modem status interrupt. For our purposes, we will only check if this is related to autobaud. */
2368  case ENUM_UART_IIR_STAT_EDSSI:
2369  {
2370 #if (ADI_UART_CFG_ENABLE_AUTOBAUD == 1)
2371  /* Initialize the autobaud event to 0. */
2372  uint32_t nEvent = 0u;
2373 
2374  /* Get the autobaud interrupt status but not the counter value. */
2375  uint16_t nStatus = hDevice->pUARTRegs->ASRL & 0xFu;
2376 
2377  /* Read the autobaud control register to see if autobaud was enabled. */
2378  uint16_t acr = (hDevice->pUARTRegs->ACR & BITM_UART_ACR_ABE);
2379 
2380  /* If there is an autobaud event and autobaud is enabled */
2381  if((nStatus != 0u) && (acr != 0u))
2382  {
2383  uint32_t nClock;
2384  uint32_t nCount;
2385 
2386  /*Get the clock frequency. */
2388  {
2389  nClock = 0u;
2390  }
2391 
2392  /* Get the autobaud counter bits 12-19. */
2393  nCount = (uint32_t)hDevice->pUARTRegs->ASRH << 12u;
2394 
2395  /* Get the autobaud counter bits 0-11. */
2396  nCount |= (uint32_t)hDevice->pUARTRegs->ASRL >> 4u;
2397 
2398  /* if the autobaud event was that the autobaud is done.. */
2399  if((nStatus & BITM_UART_ASRL_DONE) == BITM_UART_ASRL_DONE)
2400  {
2401  /* If the fractional baud generator is enabled, calculate the fractional portional of the baudrate.
2402  It seems that in order to get a correct baudrate reading, we need the fractional divider enabled.
2403  */
2404  if ((hDevice->pUARTRegs->FBR & 0x8000u) == 0x8000u)
2405  {
2406  uint8_t nOSR = 0u;
2407  uint32_t nDivN;
2408  uint32_t nDivNSubtractor = 2048u;
2409 
2410  /* DIVC is always 1, unless the oversample rate is 32. */
2411  uint16_t nDivC = 1u;
2412 
2413  /* If the oversample rate is 4.. */
2414  if(nCount < (8u << 3u))
2415  {
2416  nDivN = ((nCount << 9u) / 8u) - nDivNSubtractor;
2417  }
2418 
2419  /* If the oversample rate is 8.. */
2420  else if(nCount < (8u << 4u))
2421  {
2422  nDivN = ((nCount << 8u) / 8u) - nDivNSubtractor;
2423  nOSR = 1u;
2424  }
2425 
2426  /* If the oversample rate is 16.. */
2427  else if(nCount < (8u << 5u))
2428  {
2429  nDivN = ((nCount << 7u) / 8u) - nDivNSubtractor;
2430  nOSR = 2u;
2431  }
2432 
2433  /* If the oversample rate is 32.. */
2434  else
2435  {
2436  nDivC = (uint16_t) (nCount / 32u / 8u);
2437  nDivN = ((nCount << 6u) / (8u * nDivC)) - nDivNSubtractor;
2438  nOSR = 3u;
2439  }
2440 
2441  /* Write back the register contents for baudrate detection in the hardware. */
2442  adi_uart_ConfigBaudRate(hDevice, nDivC, 1u, (uint16_t)nDivN, nOSR);
2443 
2444  /* For more precise calculations we would use floating point math here. Integer precision will do for now.
2445  This avoids bringing in extra libraries for floating point math. */
2446 
2447  /* Baudrate = (UARTCLK / (nDivM + nDivN / 2048) * pow(2, nOSR + 2) * nDivC)
2448  nOSR = (1u << (nOSR + 2u)); Seperate this out of the equation for misra compliance
2449  hDevice->nBaudRate = ((float)nClock / (((float)1 + (float)nDivN / (float)2048) * (float)nOSR * (float)nDivC));
2450  */
2451 
2452  /* In order to avoid bringing in the extra floating point libraries, we will use the non fractional baudrate for the API. */
2453  hDevice->nBaudRate = ((nClock * 8u) / nCount);
2454  }
2455  else
2456  {
2457  /* No Fractional divider: Baudrate (bits/second) = (UARTCLK (cycles/second) * counted bits (bits)) / nCount (cycles)*/
2458  hDevice->nBaudRate = ((nClock * 8u) / nCount);
2459  }
2460 
2461  /* If there is a callback, notify the API that autobaud is complete.
2462  If there is not a callback, the baudrate will be set to a non zero value so the user can call "Get_BaudRate"
2463  to know that autobaud has completed.
2464  */
2465  if((hDevice->pfCallback != NULL) && (hDevice->bAutobaudCallbackMode == true))
2466  {
2467  hDevice->pfCallback(hDevice->pCBParam, ADI_UART_EVENT_AUTOBAUD_COMPLETE, (void*)hDevice->nBaudRate);
2468  }
2469  }
2470  else
2471  {
2472  if((nStatus & BITM_UART_ASRL_BRKTO) == BITM_UART_ASRL_BRKTO)
2473  {
2474  /* Autobaud timed out due to break error. */
2475  nEvent |= (uint32_t)ADI_UART_AUTOBAUD_TIMEOUT_LONGBREAK;
2476  }
2477  if((nStatus & BITM_UART_ASRL_NSETO) == BITM_UART_ASRL_NSETO)
2478  {
2479  /* Autobaud timed out due to no valid start edge found. */
2480  nEvent |= (uint32_t)ADI_UART_AUTOBAUD_TIMEOUT_NO_START_EDGE;
2481  }
2482  if((nStatus & BITM_UART_ASRL_NEETO) == BITM_UART_ASRL_NEETO)
2483  {
2484  /* Autobaud timed out due to no valid end edge found. */
2485  nEvent |= (uint32_t)ADI_UART_AUTOBAUD_TIMEOUT_NO_END_EDGE;
2486  }
2487  /* If there is an event callback.. */
2488  if((hDevice->pfCallback != NULL) && (hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING))
2489  {
2490  /* Notify application of errors through callback. */
2491  hDevice->pfCallback(hDevice->pCBParam, ADI_UART_EVENT_AUTOBAUD_ERROR_DETECTED, (void*)nEvent);
2492  }
2493  else
2494  {
2495  /* Notify application of errors through autobaud return value. */
2496  hDevice->nAutobaudError = nEvent;
2497  }
2498 
2499  }
2500 
2501  /* Dummy read to flush the RX register to clear the key character that was sent while configuring autobaud. */
2502  hDevice->pUARTRegs->RX;
2503  }
2504 #endif
2505  /* Clear auto baud enable and interrupt registers. We disable autobaud here because it is required in order to clear the counter. */
2506  hDevice->pUARTRegs->ACR &=(uint16_t)~( BITM_UART_ACR_ABE |
2507  BITM_UART_ACR_DNIEN |
2508  BITM_UART_ACR_TOIEN );
2509 
2510  hDevice->bAutobaudInProgress = false;
2511  break;
2512  }
2513  default:
2514  break;
2515  }
2516  return;
2517 }
2518 
2519 
2520 /* DMA interrupt handlers */
2521 void DMA_UART0_TX_Int_Handler(void)
2522 {
2523  ISR_PROLOG();
2524  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[0].hDevice;
2525  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
2526 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2528 #endif
2529  ISR_EPILOG();
2530 }
2531 
2532 void DMA_UART0_RX_Int_Handler(void)
2533 {
2534  ISR_PROLOG();
2535  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[0].hDevice;
2536  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
2537 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2539 #endif
2540  ISR_EPILOG();
2541 }
2542 
2543 #if defined(__ADUCM4x50__)
2544 
2545 void DMA_UART1_TX_Int_Handler(void)
2546 {
2547  ISR_PROLOG();
2548  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[1].hDevice;
2549  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
2550 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2552 #endif
2553  ISR_EPILOG();
2554 }
2555 
2556 void DMA_UART1_RX_Int_Handler(void)
2557 {
2558  ISR_PROLOG();
2559  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[1].hDevice;
2560  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
2561 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2563 #endif
2564  ISR_EPILOG();
2565 }
2566 #endif/*__ADUCM4x50__*/
2567 /*
2568  * @brief UART interrupt handler for receiving the data in interrupt mode.
2569  *
2570  * @param [in] hDevice Device handle obtained from adi_uart_Open().
2571  * @param [in] nBytes Number of bytes to read from the RX.
2572  *
2573 */
2574 static void uart_RxDataHandler(ADI_UART_HANDLE hDevice, uint8_t nBytes)
2575 {
2576  ADI_UART_BUFF_INFO *pFillBuffer = hDevice->pChannelRx->pFillBuffer;
2577 
2578  /* Address of the buffer to be filled. */
2579  volatile uint8_t *pNextData = (uint8_t *)pFillBuffer->pStartAddress;
2580 
2581  bool activeBufferAvailable = ( (pNextData != NULL)
2582  && (pFillBuffer->bInUse == true)
2583  );
2584  /* If there is an active buffer when we enter this handler. */
2585  if(activeBufferAvailable)
2586  {
2587 
2588 #if !defined(ADI_UART_DRAIN_RX_BUFFER) || (0==ADI_UART_DRAIN_RX_BUFFER)
2589 
2590  /* Extract the required amount of data from the FIFO/Rx
2591  * Buffer must not be overwritten
2592  */
2593  while ( (nBytes-- > 0)
2594  && (pFillBuffer->nIndex < pFillBuffer->nCount)
2595  )
2596  {
2597  /* Read data from the RX holding register into the buffer
2598  * at the indexed location.
2599  */
2600  pNextData[pFillBuffer->nIndex] = (uint8_t) hDevice->pUARTRegs->RX;
2601 
2602  /* Increment the buffer index to store the next data. */
2603  pFillBuffer->nIndex++;
2604  }
2605 
2606  /* If all of the data has been processed, manage the processed data
2607  * buffer. Otherwise we will leave everything as is and continue to
2608  * receive interrupts for the incoming data, until this buffer has
2609  * been filled.
2610  */
2611  if(pFillBuffer->nIndex == pFillBuffer->nCount)
2612  {
2613  uart_ManageProcessedBuffer( hDevice, hDevice->pChannelRx
2615  }
2616 
2617 #else
2618 
2619  /* There are two main criteria for this loop:
2620  *
2621  * - there are data in the Rx FIFO
2622  * - a valid buffer is available to store the data in Rx FIFO
2623  *
2624  * We keep the number of data in the Rx FIFO up to date
2625  */
2626  while (activeBufferAvailable)
2627  {
2628  /* Get the current number of bytes available in the UART Rx FIFO */
2629  nBytes = hDevice->pUARTRegs->RFC;
2630 
2631  /* if there are no bytes left then we can leave */
2632  if (!nBytes)
2633  break;
2634 
2635  while (nBytes--)
2636  {
2637  /* Read data from the RX holding register into the buffer
2638  * at the indexed location.
2639  */
2640  pNextData[pFillBuffer->nIndex] = hDevice->pUARTRegs->RX;
2641 
2642  /* Increment the buffer index to store the next data. */
2643  pFillBuffer->nIndex++;
2644 
2645  /* If the buffer is full. */
2646  if (pFillBuffer->nIndex == pFillBuffer->nCount)
2647  {
2648  /* Try to get a new buffer */
2649  uart_ManageProcessedBuffer(hDevice,
2650  hDevice->pChannelRx,
2652 
2653  /* Pick up the newly submitted buffer */
2654  pFillBuffer = hDevice->pChannelRx->pFillBuffer;
2655  pNextData = (uint8_t *)pFillBuffer->pStartAddress;
2656 
2657  /* Make sure it's an active buffer */
2658  activeBufferAvailable = ( (pNextData != NULL)
2659  && (pFillBuffer->bInUse == true)
2660  );
2661  /* if no active buffer is available then stop looping */
2662  if (!activeBufferAvailable)
2663  {
2664  break;
2665  }
2666  }
2667  }
2668  }
2669 
2670 #endif
2671  }
2672  /* If we do not have a buffer submitted.. */
2673  else
2674  {
2675  /* Ask the API for a buffer so we can process this data before having
2676  an overflow. if there is no callback, the API will not be able to
2677  submit a buffer in time.
2678  */
2679  if (hDevice->pfCallback != NULL)
2680  {
2681  hDevice->pfCallback( hDevice->pCBParam
2683  , NULL);
2684  }
2685 
2686  /* This check here is in case in the callback the application
2687  submitted a buffer. If they did not then we need to clear
2688  the RX register in order to clear this interrupt.
2689  */
2690  if( (pFillBuffer->pStartAddress == NULL)
2691  && (pFillBuffer->bInUse == false)
2692  )
2693  {
2694  hDevice->pUARTRegs->RX;
2695  }
2696  }
2697 
2698  return;
2699 }
2700 
2701 /*
2702  * @brief UART interrupt handler transmitting the data in interrupt mode.
2703  *
2704  * @param [in] hDevice Device handle obtained from adi_uart_Open().
2705  *
2706 */
2707 static void uart_TxDataHandler(ADI_UART_HANDLE hDevice)
2708 {
2709  volatile uint8_t *pNextData;
2710 
2711  /* If there is an active buffer.. */
2712  if((hDevice->pChannelTx->pFillBuffer->pStartAddress != NULL) && (hDevice->pChannelTx->pFillBuffer->bInUse == true))
2713  {
2714  /* Get the start address of the buffer we are transmitting data from. */
2715  pNextData = (uint8_t *)hDevice->pChannelTx->pFillBuffer->pStartAddress;
2716 
2717  /* Write data to the TX holding register. This will be shifted out at the baud rate by the shift register. */
2718  hDevice->pUARTRegs->TX = (uint16_t)pNextData[hDevice->pChannelTx->pFillBuffer->nIndex];
2719 
2720  /* Increment the buffer index. */
2721  hDevice->pChannelTx->pFillBuffer->nIndex++;
2722 
2723 
2724  /* If all of the characters have been transmitted, manage the data buffer. Otherwise we will leave everything
2725  as is and continue to transmit this data until everything is out of the buffer. */
2726  if(hDevice->pChannelTx->pFillBuffer->nIndex >= hDevice->pChannelTx->pFillBuffer->nCount)
2727  {
2728  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
2729  }
2730  }
2731  return;
2732 }
2733 
2734 
2735 /*
2736  * @brief Function for managing the processed buffer. This gets called after the receive buffer has been filled
2737  * and when the transmit buffer has been emptied.
2738  *
2739  * @param [in] hDevice Device handle obtained from adi_uart_Open().
2740  * @param [in] pChannel Channel handler for the Tx or Rx.
2741  * @param [in] eEvent Indicate the event ID to be passed to registered callback function, if one has been registered.
2742  *
2743 */
2744 
2745 
2746 static void uart_ManageProcessedBuffer(ADI_UART_HANDLE hDevice,ADI_UART_DATA_CHANNEL *pChannel, ADI_UART_EVENT eEvent)
2747 {
2748 
2749 
2750  /* Now that this transaction has completed, this buffer is no longer in use. */
2751  pChannel->pFillBuffer->bInUse = false;
2752 
2753  pChannel->pFillBuffer = pChannel->pFillBuffer->pNextBuffer;
2754 
2756  {
2757  /* Disable Tx buffer interrupts. */
2758  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ETBEI | BITM_UART_IEN_EDMAT);
2759  }
2760  else
2761  {
2762  /* Disable Rx buffer interrupts for the DMA. We do not disable receive buffer full interrupts to allow
2763  the use of the RX FIFO.
2764  */
2765  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_EDMAR);
2766 
2767  if (hDevice->bRxFifoEn != true)
2768  {
2769  /* Disable Rx buffer interrupts for PIO mode if the FIFO is not enabled.
2770  */
2771  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ERBFI);
2772  }
2773 
2774  }
2775 
2776  /* If there is a callback registered, notify the API that a buffer has been processed. Clean up the buffer. */
2777  if((hDevice->pfCallback != NULL) && (pChannel->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING))
2778  {
2779  uint32_t nEvent = hDevice->nHwError;
2780  hDevice->nHwError = 0u;
2781 
2782  uint32_t *pBuffer = pChannel->pActiveBuffer->pStartAddress;
2783 
2784  /* Reinitialize the start address to NULL so this buffer can be used for a new transaction. */
2785  pChannel->pActiveBuffer->pStartAddress = NULL;
2786 
2787  /* Now that the desired data has either been transmitted or received, this buffer is no longer
2788  in use. We can update "pActiveBuffer" to point to the next buffer that will become or is already
2789  active.
2790  */
2791  pChannel->pActiveBuffer = pChannel->pActiveBuffer->pNextBuffer;
2792 
2793  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
2794  This will only be done if there are no other active buffers in flight to avoid disrupting an active transfer.
2795  */
2796 
2797  if(pChannel->pActiveBuffer->pStartAddress == NULL)
2798  {
2799  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
2800  }
2801 
2802  if(nEvent != 0u)
2803  {
2804  hDevice->pfCallback(hDevice->pCBParam, ADI_UART_EVENT_HW_ERROR_DETECTED,(void*)nEvent);
2805  }
2806  else
2807  {
2808  hDevice->pfCallback(hDevice->pCBParam, (uint32_t)eEvent, (void*)pBuffer);
2809  }
2810  /* Post to the blocking function. If we are in blocking mode, this will allow the buffer to be returned to the API.
2811  If we are in nonblocking mode, this will allow adi_uart_GetBuffer() to return immediately so the API can have
2812  control over the buffer again.
2813  */
2814  SEM_POST(pChannel);
2815  }
2816 
2817  else
2818  {
2819  /* Wait until the last bit is gone before POSTing the SEMAPHORE */
2821  while( ((hDevice->pUARTRegs->LSR & BITM_UART_LSR_TEMT) != BITM_UART_LSR_TEMT) ||(hDevice->pUARTRegs->TFC != 0u))
2822  {
2823  /*waiting until TFC becomes zero */
2824  }
2825  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
2826  This will only be done if there are no other active buffers in flight to avoid disrupting an active transfer.
2827  */
2828 
2829  if( pChannel->pActiveBuffer->pNextBuffer->pStartAddress==NULL)
2830  {
2831  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
2832  }
2833 
2834  /* Post to the blocking function. If we are in blocking mode, this will allow the buffer to be returned to the API.
2835  If we are in nonblocking mode, this will allow adi_uart_GetBuffer() to return immediately so the API can have
2836  control over the buffer again.
2837  */
2838  SEM_POST(pChannel);
2839  }
2840 
2841  /* If there is another buffer active. The buffer we want to check is "pFillBuffer" because that is the next one that would
2842  be processed. So if it has been submitted, now would be the time to set up the interrupts based on its requirements.
2843  */
2844  if(pChannel->pFillBuffer->bInUse == true)
2845  {
2846  pChannel->pfSubmitBuffer(hDevice, pChannel->pFillBuffer);
2847  }
2848 }
2849 
2850 
2851 
2852 /*
2853  * @brief Initialize the UART instance to the default values specified in "adi_uart_config.h".
2854  *
2855  * @param [in] hDevice Device handle obtained from adi_uart_Open().
2856  * @param [in] nDeviceNum UART device number
2857 */
2858 
2859 static void uart_init(ADI_UART_CONST_HANDLE const hDevice, uint32_t const nDeviceNum)
2860 {
2861 
2862  ADI_UART_CONFIG const* pUARTCfg = &gUARTCfg[nDeviceNum];
2863 
2864  /* Line Control Register. */
2865  hDevice->pUARTRegs->LCR = pUARTCfg->LCR;
2866 
2867  /* Div-C in Baudrate divider register. */
2868  hDevice->pUARTRegs->DIV = pUARTCfg->DIV;
2869 
2870  /* Div-M and Div-N in Fractional Baudrate register. */
2871  hDevice->pUARTRegs->FBR = pUARTCfg->FBR;
2872 
2873  /* Second line control register. */
2874  hDevice->pUARTRegs->LCR2 = pUARTCfg->LCR2;
2875 
2876  /* FIFO control register. */
2877  hDevice->pUARTRegs->FCR = pUARTCfg->FCR;
2878 
2879  /* Half Duplex Control Register. */
2880  hDevice->pUARTRegs->RSC = pUARTCfg->RSC;
2881 
2882  /* Interrupt enable register. */
2883  hDevice->pUARTRegs->IEN = pUARTCfg->IEN;
2884 }
2885 
2886 #ifdef ADI_DEBUG
2887 /*
2888  * @brief Validate the device handle.
2889  *
2890  * @param [in] hDevice Device handle obtained from adi_uart_Open().
2891  *
2892  * @return Status
2893  * - #ADI_UART_SUCCESS Specified handle is valid.
2894  * - #ADI_UART_INVALID_HANDLE Specified handle is invalid.
2895  *
2896 */
2897 
2898 static ADI_UART_RESULT ValidateHandle(ADI_UART_CONST_HANDLE hDevice)
2899 {
2900  uint32_t i;
2901 
2902 
2903  for(i = 0U; i < ADI_UART_NUM_DEVICES; i++)
2904  {
2905 
2906  if((hDevice == uart_device_info[i].hDevice) && (hDevice != NULL))
2907  {
2908  return(ADI_UART_SUCCESS);
2909  }
2910  }
2911  return(ADI_UART_INVALID_HANDLE);
2912 }
2913 
2914 #endif /* ADI_DEBUG */
2915 
#define ADI_UART0_CFG_DIVC
ADI_DMA_RESULT adi_dma_RegisterCallback(DMA_CHANn_TypeDef const eChannelID, ADI_CALLBACK const pfCallback, void *const pCBParam)
Register a call-back function for a DMA channel.
Definition: adi_dma.c:223
ADI_UART_RESULT
Definition: adi_uart.h:138
#define ADI_UART1_CFG_STOP_BIT
#define ADI_UART0_CFG_ENABLE_STICKY_PARITY
#define ADI_CYCLECOUNT_STORE(id)
#define ADI_UART1_CFG_DIVC
ADI_UART_RESULT adi_uart_Close(ADI_UART_HANDLE const hDevice)
Uninitialize the memory for the specified UART instance.
Definition: adi_uart.c:507
#define ADI_CYCLECOUNT_ISR_UART
ADI_UART_RESULT adi_uart_SetConfiguration(ADI_UART_HANDLE const hDevice, ADI_UART_PARITY const eParity, ADI_UART_STOPBITS const eStopBits, ADI_UART_WORDLEN const eWordLength)
Configuration of UART data.
Definition: adi_uart.c:1689
#define ADI_UART0_CFG_TRIG_LEVEL
ADI_UART_TRIG_LEVEL
Definition: adi_uart.h:236
#define ADI_UART1_CFG_ENABLE_PARITY
#define ADI_UART0_CFG_WORD_LENGTH
ADI_UART_RESULT adi_uart_IsRxBufferAvailable(ADI_UART_HANDLE const hDevice, bool *const pbAvailable)
Peek function to know if a filled buffer is available.
Definition: adi_uart.c:1537
#define ADI_UART0_CFG_DEASSERTION
#define ADI_UART0_CFG_DIVN
#define ADI_UART0_CFG_PARITY_SELECTION
#define ADI_UART_NUM_DEVICES
Definition: adi_uart.c:204
#define ADI_UART1_CFG_DISABLE_RX
#define ADI_UART1_CFG_OSR
#define ADI_UART0_CFG_STOP_BIT
ADI_UART_RESULT adi_uart_SetRxFifoTriggerLevel(ADI_UART_HANDLE const hDevice, ADI_UART_TRIG_LEVEL const eTriglevel)
Sets the RX FIFO trigger level. This will be the amount of data in the FIFO that will trigger an inte...
Definition: adi_uart.c:2028
ADI_UART_RESULT adi_uart_GetRxBuffer(ADI_UART_HANDLE const hDevice, void **const ppBuffer, uint32_t *pHwError)
Transfer buffer ownership from the device back to the API if the data receive has completed...
Definition: adi_uart.c:1028
#define ADI_UART1_CFG_ENABLE_STICKY_PARITY
ADI_UART_RESULT adi_uart_FlushTxFifo(ADI_UART_CONST_HANDLE const hDevice)
To flush the TX FIFO.
Definition: adi_uart.c:2108
ADI_UART_RESULT adi_uart_SubmitTxBuffer(ADI_UART_HANDLE const hDevice, void *const pBuffer, uint32_t const nBufSize, bool const bDMA)
Submit a "filled" buffer for transmitting data in ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING. This function sets up the apropriate interrupts associated with the transaction and marks the buffer as submitted.
Definition: adi_uart.c:594
ADI_UART_RESULT adi_uart_RegisterCallback(ADI_UART_HANDLE const hDevice, const ADI_CALLBACK pfCallback, void *const pCBParam)
Registering a callback function.
Definition: adi_uart.c:1638
#define ADI_UART0_CFG_OSR
ADI_UART_RESULT adi_uart_FlushRxChannel(ADI_UART_CONST_HANDLE const hDevice)
Flush the Rx channel and disable interrupts. This will stop any buffers in flight and clear out any d...
Definition: adi_uart.c:2170
ADI_UART_RESULT adi_uart_FlushTxChannel(ADI_UART_CONST_HANDLE const hDevice)
Flush the Tx channel and disable interrupts.This will stop any buffers in flight and clear out any da...
Definition: adi_uart.c:2221
ADI_UART_DIRECTION
Definition: adi_uart.h:98
#define ADI_UART1_CFG_ENABLE_RX_STATUS_INTERRUPT
#define ADI_CYCLECOUNT_ISR_DMA_UART_RX
#define ADI_UART1_CFG_DEASSERTION
ADI_UART_RESULT adi_uart_EnableFifo(ADI_UART_HANDLE const hDevice, bool const bEnable)
Enables internal FIFO as to work in 16550 mode. This helps to minimize system overhead and maximize s...
Definition: adi_uart.c:2063
ADI_UART_RESULT adi_uart_GetTxBuffer(ADI_UART_HANDLE const hDevice, void **const ppBuffer, uint32_t *pHwError)
Transfer buffer ownership from the device back to the API if the data transmit has completed...
Definition: adi_uart.c:970
#define ADI_UART0_CFG_ENABLE_MODEM_STATUS_INTERRUPT
ADI_UART_WORDLEN
Definition: adi_uart.h:254
ADI_UART_RESULT adi_uart_SubmitRxBuffer(ADI_UART_HANDLE const hDevice, void *const pBuffer, uint32_t const nBufSize, bool const bDMA)
Submit an empty buffer for receiving the data in ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING. This will set up the Rx channel for notification on incoming data using either the DMA or UART interrupts, as well as mark the buffer as submitted.
Definition: adi_uart.c:784
#define ADI_UART0_CFG_ENABLE_RX_STATUS_INTERRUPT
#define ADI_UART0_CFG_DISABLE_RX
ADI_UART_RESULT adi_uart_Write(ADI_UART_HANDLE const hDevice, void *const pBuffer, uint32_t const nBufSize, bool const bDMA, uint32_t *pHwError)
Submit the buffer for transmitting the data in ADI_UART_DATA_TRANSFER_MODE_BLOCKING. Call to this function will not return until the entire buffer is transmitted. Returns error if this function is called when device is operating in ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING. i.e Function "adi_uart_SubmitTxBuffer()" is called and the transfer is not yet complete.
Definition: adi_uart.c:1166
#define ADI_UART0_CFG_HOLD_TX
#define ADI_UART_BIDIR_MEMORY_SIZE
Definition: adi_uart.h:81
ADI_UART_RESULT adi_uart_FlushRxFifo(ADI_UART_CONST_HANDLE const hDevice)
Flush the RX FIFO.
Definition: adi_uart.c:2138
ADI_UART_RESULT adi_uart_ForceTxBreak(ADI_UART_HANDLE const hDevice, bool const bEnable)
Forces the UART to send out a break signal.
Definition: adi_uart.c:1950
ADI_PWR_RESULT adi_pwr_GetClockFrequency(const ADI_CLOCK_ID eClockId, uint32_t *pClock)
Get the frequency of the given clock. Obtain individual peripheral clock frequencies.
Definition: adi_pwr.c:467
ADI_UART_RESULT adi_uart_Read(ADI_UART_HANDLE const hDevice, void *const pBuffer, uint32_t const nBufSize, bool const bDMA, uint32_t *pHwError)
Submit the buffer for reading the data in ADI_UART_DATA_TRANSFER_MODE_BLOCKING. Call to this function...
Definition: adi_uart.c:1298
ADI_UART_PARITY
Definition: adi_uart.h:271
ADI_UART_RESULT adi_uart_EnableLoopBack(ADI_UART_HANDLE const hDevice, bool const bEnable)
Enable/Disable the loopback for the specified UART device.
Definition: adi_uart.c:1989
#define ADI_UART1_CFG_SOUT_POLARITY
ADI_UART_RESULT adi_uart_IsTxBufferAvailable(ADI_UART_HANDLE const hDevice, bool *const pbAvailable)
Peek function to know if an empty buffer is avilable.
Definition: adi_uart.c:1481
#define ADI_UART1_CFG_DIVN
ADI_UART_EVENT
Definition: adi_uart.h:114
#define ADI_UART1_CFG_TRIG_LEVEL
struct _ADI_UART_DEVICE * ADI_UART_HANDLE
Definition: adi_uart.h:86
#define ADI_CYCLECOUNT_ISR_DMA_UART_TX
ADI_UART_STOPBITS
Definition: adi_uart.h:290
#define ADI_UART1_CFG_PARITY_SELECTION
ADI_UART_RESULT adi_uart_Open(uint32_t const nDeviceNum, ADI_UART_DIRECTION const eDirection, void *pMemory, uint32_t const nMemSize, ADI_UART_HANDLE *const phDevice)
Initialization function for the UART device.
Definition: adi_uart.c:315
#define ADI_UART1_CFG_HOLD_TX
#define ADI_UART0_CFG_DIVM
#define ADI_UART1_CFG_WORD_LENGTH
const struct _ADI_UART_DEVICE * ADI_UART_CONST_HANDLE
Definition: adi_uart.h:91
void adi_dma_Init(void)
Initialize the DMA peripheral.
Definition: adi_dma.c:175
#define ADI_UART1_CFG_ENABLE_FIFO
#define ADI_UART0_CFG_ENABLE_FIFO
ADI_UART_RESULT adi_uart_IsTxComplete(ADI_UART_HANDLE const hDevice, bool *const pbComplete)
Function to let the API know if all the data had been drained from the Tx shift registers.
Definition: adi_uart.c:1596
ADI_UART_RESULT adi_uart_ConfigBaudRate(ADI_UART_HANDLE const hDevice, uint16_t const nDivC, uint8_t const nDivM, uint16_t const nDivN, uint8_t const nOSR)
Set baudrate by configuring the fractional dividors.
Definition: adi_uart.c:1751
ADI_UART_RESULT adi_uart_EnableAutobaud(ADI_UART_HANDLE const hDevice, bool const bEnable, bool const bAutobaudCallbackMode)
Enable/Disable UART autobaud detection as well as configures the device for autobaud detection...
Definition: adi_uart.c:1878
#define ADI_UART1_CFG_DIVM
#define ADI_UART0_CFG_SOUT_POLARITY
ADI_UART_RESULT adi_uart_GetBaudRate(ADI_UART_HANDLE const hDevice, uint32_t *pnBaudRate, uint32_t *pAutobaudError)
Get the baudrate of the UART device instance. This is used in the scenario when a callback has not be...
Definition: adi_uart.c:1809
#define ADI_UART_UNIDIR_MEMORY_SIZE
Definition: adi_uart.h:76
#define ADI_UART0_CFG_ENABLE_PARITY
#define ADI_UART1_CFG_ENABLE_MODEM_STATUS_INTERRUPT