ADuCM4x50 Device Drivers API Reference Manual  Release 4.0.0.0
adi_uart.c
1 
26 #include <drivers/uart/adi_uart.h>
27 #include <drivers/dma/adi_dma.h>
28 #include "adi_uart_def.h"
29 #include <adi_cyclecount.h>
30 
31 
32 #ifdef __ICCARM__
33 /*
34 * IAR MISRA C 2004 error suppressions.
35 *
36 * Pm50: (MISRA C 2004 rule 14.3): a null statement shall only occur on a line by itself,
37 * and shall not have any other text on the same line
38 * Some Macros, such as ISR_PROLOGUE, may not have any expansion
39 * resulting in just the terminating ';'.
40 *
41 * Pm073 (rule 14.7): A function should have a single point of exit.
42 * Pm143 (rule 14.7): A function should have a single point of exit at the end of the function.
43 * Multiple returns are used for error handling.
44 *
45 * Pm088 (rule 17.4): Pointer arithmetic should not be used.
46 * Relying on pointer arithmetic for buffer handling.
47 *
48 * Pm123 (rule 18.5): There shall be no definition of objects in a header file.
49 *
50 * Pm140 (rule 11.3): A cast should not be performed between a pointer type and an integral type.
51 * MMR addresses are defined as simple constants. Accessing the MMR requires casting to a pointer type.
52 *
53 * Pm152 (rule 17.4): Array indexing shall only be applied to objects defined as an array type.
54 * Relying on pointer arithmetic for buffer handling and
55 * Accessing the DMA descriptors, which are defined in the system as a pointer to an array of descriptors.
56 *
57 * Pm008: Code should not be commented out.
58  This code was commented out to show what the autobaud equations would look like if there were floating point precision.
59  Ideally this would be the case but for the sake of footprint size we will leave it at single point precision.
60 */
61 #pragma diag_suppress=Pm050,Pm073,Pm088,Pm123,Pm140,Pm143,Pm152,Pm008,Pm026
62 #endif /* __ICCARM__ */
63 
64 
65 
66 
67 /**********************************************************
68  * UART Data
69  **********************************************************/
70 static ADI_UART_DEVICE_INFO uart_device_info[ ] =
71 {
72  {
73  UART0_TX_CHANn,
74  UART0_RX_CHANn,
75  DMA0_CH8_DONE_IRQn,
76  DMA0_CH9_DONE_IRQn,
77  (IRQn_Type)INTR_UART0_EVT,
78  pADI_UART0,
79  NULL
80  },
81 #if defined (__ADUCM4x50__)
82  {
83  UART1_TX_CHANn,
84  UART1_RX_CHANn,
85  DMA0_CH25_DONE_IRQn,
86  DMA0_CH26_DONE_IRQn,
87  (IRQn_Type)INTR_UART1_EVT,
88  pADI_UART1,
89  NULL
90  },
91 #endif /* __ADUCM4x50 */
92 };
93 
94 static const ADI_UART_CONFIG gUARTCfg[ ] =
95 {
96  {
97  /* Line control register. */
98  ((ADI_UART0_CFG_WORD_LENGTH << BITP_UART_LCR_WLS) |
99  (ADI_UART0_CFG_STOP_BIT << BITP_UART_LCR_STOP) |
100  (ADI_UART0_CFG_ENABLE_PARITY << BITP_UART_LCR_PEN) |
101  (ADI_UART0_CFG_PARITY_SELECTION << BITP_UART_LCR_EPS) |
102  (ADI_UART0_CFG_ENABLE_STICKY_PARITY << BITP_UART_LCR_SP)),
103 
104  /* Div-C in baudrate divider register. */
106 
107  /* Div-M and Div-N in fractional baudrate Register. */
108  (((uint32_t)ADI_UART0_CFG_DIVN << BITP_UART_FBR_DIVN) |
109  ((uint32_t)ADI_UART0_CFG_DIVM << BITP_UART_FBR_DIVM) |
110  ((uint32_t)BITM_UART_FBR_FBEN)),
111 
112  /* Over sample rate in second line control register. */
114 
115  /* FIFO control register. */
116  ((ADI_UART0_CFG_ENABLE_FIFO << BITP_UART_FCR_FIFOEN)|
117  (ADI_UART0_CFG_TRIG_LEVEL << BITP_UART_FCR_RFTRIG)),
118 
119  /* Half duplex control register. */
120  ((ADI_UART0_CFG_SOUT_POLARITY << BITP_UART_RSC_OENP) |
121  (ADI_UART0_CFG_DEASSERTION << BITP_UART_RSC_OENSP) |
122  (ADI_UART0_CFG_DISABLE_RX << BITP_UART_RSC_DISRX) |
123  (ADI_UART0_CFG_HOLD_TX << BITP_UART_RSC_DISTX)),
124 
125  /* Interrupt enable register. */
126  ((ADI_UART0_CFG_ENABLE_MODEM_STATUS_INTERRUPT << BITP_UART_IEN_EDSSI) |
127  (ADI_UART0_CFG_ENABLE_RX_STATUS_INTERRUPT << BITP_UART_IEN_ELSI))
128 
129  },
130 #if defined (__ADUCM4x50__)
131  {
132  /* Line control register. */
133  ((ADI_UART1_CFG_WORD_LENGTH << BITP_UART_LCR_WLS) |
134  (ADI_UART1_CFG_STOP_BIT << BITP_UART_LCR_STOP) |
135  (ADI_UART1_CFG_ENABLE_PARITY << BITP_UART_LCR_PEN) |
136  (ADI_UART1_CFG_PARITY_SELECTION << BITP_UART_LCR_EPS) |
137  (ADI_UART1_CFG_ENABLE_STICKY_PARITY << BITP_UART_LCR_SP)),
138 
139  /* Div-C in Baudrate divider register. */
141 
142  /* Div-M and Div-N in fractional baudrate Register. */
143  (((uint32_t)ADI_UART1_CFG_DIVN << BITP_UART_FBR_DIVN) |
144  ((uint32_t)ADI_UART1_CFG_DIVM << BITP_UART_FBR_DIVM) |
145  ((uint32_t)BITM_UART_FBR_FBEN)),
146 
147  /* Over sample rate in second line control register. */
149 
150  /* FIFO control register. */
151  ((ADI_UART1_CFG_ENABLE_FIFO << BITP_UART_FCR_FIFOEN)|
152  (ADI_UART1_CFG_TRIG_LEVEL << BITP_UART_FCR_RFTRIG)),
153 
154  /* Half duplex control register. */
155  ((ADI_UART1_CFG_SOUT_POLARITY << BITP_UART_RSC_OENP) |
156  (ADI_UART1_CFG_DEASSERTION << BITP_UART_RSC_OENSP) |
157  (ADI_UART1_CFG_DISABLE_RX << BITP_UART_RSC_DISRX) |
158  (ADI_UART1_CFG_HOLD_TX << BITP_UART_RSC_DISTX)),
159 
160  /* Interrupt enable register. */
161  ((ADI_UART1_CFG_ENABLE_MODEM_STATUS_INTERRUPT << BITP_UART_IEN_EDSSI) |
162  (ADI_UART1_CFG_ENABLE_RX_STATUS_INTERRUPT << BITP_UART_IEN_ELSI))
163  }
164 #endif /*__ADUCM4x50*/
165 };
166 
167 /* Number of bytes received before Rx interrupt triggers. */
168 static const uint8_t sFifoTriggers[] = {1u, 4u, 8u, 14u};
169 
173 #define ADI_UART_NUM_DEVICES (sizeof(uart_device_info)/sizeof(ADI_UART_DEVICE_INFO))
174 
175 /* Override "weak" default binding in startup.c */
177 extern void UART0_Int_Handler(void);
178 extern void UART1_Int_Handler(void);
179 extern void DMA_UART0_TX_Int_Handler(void);
180 extern void DMA_UART0_RX_Int_Handler(void);
181 
182 #if defined (__ADUCM4x50__)
183 extern void DMA_UART1_TX_Int_Handler(void);
184 extern void DMA_UART1_RX_Int_Handler(void);
185 #endif
186 
187 /* Internal DMA Callback for receiving DMA faults from common DMA error handler. */
188 static void RxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg);
189 static void RxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg) {
190 
191  /* Recover the device handle. */
192  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)pCBParam;
193  ADI_UART_BUFF_INFO * pNextBuff = hDevice->pChannelRx->pFillBuffer->pNextBuffer;
194  uint32_t nEvent = 0u;
195 
196  /* Save the DMA error. */
197  switch (Event) {
199  nEvent |= (uint32_t)ADI_UART_HW_ERR_RX_CHAN_DMA_BUS_FAULT;
200  break;
202  nEvent |= (uint32_t)ADI_UART_HW_ERR_RX_CHAN_DMA_INVALID_DESCR;
203  break;
204  default:
205  nEvent |= (uint32_t)ADI_UART_HW_ERR_RX_CHAN_DMA_UNKNOWN_ERROR;
206  break;
207  }
208 
209  if((pNextBuff->pStartAddress != NULL) && (pNextBuff->bDMA == true))
210  {
211  hDevice->nHwError |= nEvent;
212  pNextBuff->bInUse = false;
213  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
214 
215  }
216  hDevice->nHwError |= nEvent;
217  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
218 }
219 
220 static void TxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg);
221 static void TxDmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg) {
222 
223  /* Recover the device handle. */
224  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)pCBParam;
225  ADI_UART_BUFF_INFO * pNextBuff = hDevice->pChannelTx->pFillBuffer->pNextBuffer;
226  uint32_t nEvent = 0u;
227 
228  /* Save the DMA error. */
229  switch (Event) {
231  nEvent |= (uint32_t)ADI_UART_HW_ERR_TX_CHAN_DMA_BUS_FAULT;
232  break;
234  nEvent |= (uint32_t)ADI_UART_HW_ERR_TX_CHAN_DMA_INVALID_DESCR;
235  break;
236  default:
237  nEvent |= (uint32_t)ADI_UART_HW_ERR_TX_CHAN_DMA_UNKNOWN_ERROR;
238  break;
239  }
240  if((pNextBuff->pStartAddress != NULL) && (pNextBuff->bDMA == true))
241  {
242  hDevice->nHwError |= nEvent;
243  pNextBuff->bInUse = false;
244  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
245 
246  }
247 
248  hDevice->nHwError |= nEvent;
249  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
250 }
253 /**********************************************************
254  * General UART APIs
255  **********************************************************/
256 
285  uint32_t const nDeviceNum,
286  ADI_UART_DIRECTION const eDirection,
287  void *pMemory,
288  uint32_t const nMemSize,
289  ADI_UART_HANDLE *const phDevice
290  )
291 {
292  uint16_t regFifoTrig = 0u;
293 
294 #ifdef ADI_DEBUG
295  /* Check if the given device number is within the range of UART
296  * devices present in the processor. There are two devices present here
297  * so this can be a 0 or 1 for ADuCM4050 and only 0 for ADuCM302x.
298  */
299  if(nDeviceNum >= ADI_UART_NUM_DEVICES)
300  {
302  }
303 
304  /* Verify the device is not already open. */
305  if(uart_device_info[nDeviceNum].hDevice != NULL)
306  {
307  return(ADI_UART_DEVICE_IN_USE);
308  }
309 
310  /* Make sure there is enough memory for the device instance to operate in a single direction. */
311  if(eDirection != ADI_UART_DIR_BIDIRECTION)
312  {
313  if(nMemSize < (uint32_t)ADI_UART_UNIDIR_MEMORY_SIZE)
314  {
316  }
317  assert(nMemSize == (sizeof(ADI_UART_DEVICE) + sizeof(ADI_UART_DATA_CHANNEL)));
318  }
319 
320  /* Make sure there is enough memory for the device instance to operate in both directions. */
321  else
322  {
323  if(nMemSize < (uint32_t)ADI_UART_BIDIR_MEMORY_SIZE)
324  {
326  }
327  assert(nMemSize == (sizeof(ADI_UART_DEVICE) + (sizeof(ADI_UART_DATA_CHANNEL)*2u)));
328  }
329 #endif /* ADI_DEBUG */
330 
331  /* Initialize the device handle to NULL in case of a failure. */
332  *phDevice = NULL;
333 
334  /* Link the ADI_UART_HANDLE to the ADI_UART_DEVICE structure. */
335  ADI_UART_HANDLE hDevice = pMemory;
336 
337  /* Zero the device handle memory so we do not have to explicitely initialize
338  the structure members to 0.
339  */
340  memset(pMemory, 0, nMemSize);
341 
342  /* Set the device information. */
343  hDevice->pUartInfo = &uart_device_info[nDeviceNum];
344 
345  /* Set the base of the UART register address. We do this to minimize
346  the cycle count when accessing the UART registers.
347  */
348  hDevice->pUARTRegs = uart_device_info[nDeviceNum].pUartRegs;
349 
350  /* Store the direction that this device will operate in. */
351  hDevice->eDirection = eDirection;
352 
353  /* Increment the device handle with the size of the UART device structure
354  so we can set the channel data next without overwriting
355  the #ADI_UART_DEVICE data.
356  */
357  pMemory = ((uint8_t *)pMemory +(sizeof(ADI_UART_DEVICE)));
358 
359  /* Set up the DMA Controller. */
360  adi_dma_Init();
361 
362  /* Initialize the TX-channel. */
363  if(ADI_UART_DIR_RECEIVE != eDirection)
364  {
365  hDevice->pChannelTx = (ADI_UART_DATA_CHANNEL *)pMemory;
366 
367  /* Initialize the data transfer mode. */
368  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
369 
370  /* Initialize Tx buffer pointers. */
371  hDevice->pChannelTx->pFreeBuffer = &hDevice->pChannelTx->PingPong[0];
372  hDevice->pChannelTx->pActiveBuffer = &hDevice->pChannelTx->PingPong[0];
373  hDevice->pChannelTx->pFillBuffer = &hDevice->pChannelTx->PingPong[0];
374 
375 
376  /* Create a "semaphore" (varies per OS) used for blocking buffer resource management. */
377  SEM_CREATE(hDevice->pChannelTx, "UART_TX_SEM", ADI_UART_SEMAPHORE_FAILED);
378 
379  /* Set submit buffer function pointer. */
380  hDevice->pChannelTx->pfSubmitBuffer = &uart_submittxbuffer;
381 
382  hDevice->pChannelTx->PingPong[0].pNextBuffer = &hDevice->pChannelTx->PingPong[1];
383  hDevice->pChannelTx->PingPong[1].pNextBuffer = &hDevice->pChannelTx->PingPong[0];
384 
385  /*Register DMA Callback. */
386  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(hDevice->pUartInfo->dmaTxChannelNum, TxDmaErrorCallback, (void*)hDevice))
387  {
388  adi_uart_Close(hDevice);
390  }
391 
392  /* Increment the device handle the size of #ADI_UART_DATA_CHANNEL
393  structure in case there is another channel to configure.
394  */
395  pMemory = ((uint8_t *)pMemory + sizeof(ADI_UART_DATA_CHANNEL));
396  }
397  /* Initialize the RX-channel. */
398  if(ADI_UART_DIR_TRANSMIT != eDirection)
399  {
400  hDevice->pChannelRx = (ADI_UART_DATA_CHANNEL *)pMemory;
401 
402  /* Initialize the data transfer mode. */
403  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
404 
405  /* Initialize Rx buffer pointers. */
406  hDevice->pChannelRx->pFreeBuffer = &hDevice->pChannelRx->PingPong[0];
407  hDevice->pChannelRx->pActiveBuffer = &hDevice->pChannelRx->PingPong[0];
408  hDevice->pChannelRx->pFillBuffer = &hDevice->pChannelRx->PingPong[0];
409 
410  /* Create a "semaphore" (varies per OS) used for blocking buffer resource management. */
411  SEM_CREATE(hDevice->pChannelRx, "UART_RX_SEM", ADI_UART_SEMAPHORE_FAILED);
412 
413  /* Set submit buffer function pointer. */
414  hDevice->pChannelRx->pfSubmitBuffer = &uart_submitrxbuffer;
415 
416  hDevice->pChannelRx->PingPong[0].pNextBuffer = &hDevice->pChannelRx->PingPong[1];
417  hDevice->pChannelRx->PingPong[1].pNextBuffer = &hDevice->pChannelRx->PingPong[0];
418 
419  /*Register DMA Callback. */
420  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(hDevice->pUartInfo->dmaRxChannelNum, RxDmaErrorCallback, (void*)hDevice))
421  {
422  adi_uart_Close(hDevice);
424  }
425  }
426 
427  /* Initialize the device with the static config values.*/
428  uart_init(hDevice, nDeviceNum);
429 
430  /* Extract the FIFO and FIFO trigger settings. These are required
431  * in the Rx interrupt handler to extract the right amount of data
432  * on each Rx interrupt */
433  hDevice->bRxFifoEn = ((hDevice->pUARTRegs->FCR & BITM_UART_FCR_FIFOEN) > 0u);
434  regFifoTrig = ((hDevice->pUARTRegs->FCR & BITM_UART_FCR_RFTRIG) >> BITP_UART_FCR_RFTRIG);
435 
436  hDevice->nRxFifoTrig = sFifoTriggers[regFifoTrig];
437 
438  /* Write the device data pointer to the application's handle. */
439  *phDevice = hDevice;
440 
441  /* Store the device handle. */
442  uart_device_info[nDeviceNum].hDevice = hDevice;
443 
444 
445  /* Enable UART Interrupt. */
446  NVIC_ClearPendingIRQ(hDevice->pUartInfo->eIRQn);
447  NVIC_EnableIRQ(hDevice->pUartInfo->eIRQn);
448 
449  /* Enable the interrupt for the DMA. */
450  NVIC_EnableIRQ(hDevice->pUartInfo->eDMATx);
451  NVIC_EnableIRQ(hDevice->pUartInfo->eDMARx);
452 
453  /* Return SUCCESS */
454  return(ADI_UART_SUCCESS);
455 }
456 
476  ADI_UART_HANDLE const hDevice
477  )
478 {
479 #ifdef ADI_DEBUG
480  /* Validate the given handle. */
481  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
482  {
483  return(ADI_UART_INVALID_HANDLE);
484  }
485 
486  /* Make sure there are no active buffers on any active channel, autobaud is not in progress and the
487  Tx shift register is completely empty. This can be an issue if you submitted a nonblocking transmit
488  because you will receive interrupt before the hardware has fully finished the transaction. The start
489  address of the active buffer will remain in use until the buffer has been completely processed.
490  Therefore if the start address is NULL it means it has not been submitted for a transaction.
491  */
492  if(((hDevice->pUARTRegs->LSR & BITM_UART_LSR_TEMT) != BITM_UART_LSR_TEMT) ||
493  ((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pFillBuffer->pStartAddress != NULL)) ||
494  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pFillBuffer->pStartAddress != NULL)) ||
495  (hDevice->bAutobaudInProgress == true))
496  {
497  return(ADI_UART_DEVICE_IN_USE);
498  }
499 #endif /* ADI_DEBUG */
500 
501  /* Disable UART status interrupts. */
502  hDevice->pUARTRegs->IEN = 0x00U;
503 
504  /* Disable DMA UART interrupts. */
505  NVIC_DisableIRQ(hDevice->pUartInfo->eDMARx);
506  NVIC_DisableIRQ(hDevice->pUartInfo->eDMATx);
507 
508  /* Disable UART event interrupt. */
509  NVIC_DisableIRQ(hDevice->pUartInfo->eIRQn);
510 
511  /* Delete Tx-Channel semaphore. */
512  if(hDevice->eDirection != ADI_UART_DIR_RECEIVE)
513  {
514  SEM_DELETE(hDevice->pChannelTx, ADI_UART_SEMAPHORE_FAILED);
515  }
516 
517  /* Delete Rx-Channel semaphore. */
518  if(hDevice->eDirection != ADI_UART_DIR_TRANSMIT)
519  {
520  SEM_DELETE(hDevice->pChannelRx, ADI_UART_SEMAPHORE_FAILED);
521  }
522 
523  /* Free up the device memory. */
524  hDevice->pUartInfo->hDevice = NULL;
525 
526  return(ADI_UART_SUCCESS);
527 }
528 
563  ADI_UART_HANDLE const hDevice,
564  void *const pBuffer,
565  uint32_t const nBufSize,
566  bool const bDMA
567  )
568 {
569 
570 #ifdef ADI_DEBUG
571  /* Validate the device handle. */
572  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
573  {
574  return(ADI_UART_INVALID_HANDLE);
575  }
576 
577  /* Validate the pointer to the buffer memory. */
578  if(pBuffer == NULL)
579  {
580  return(ADI_UART_INVALID_POINTER);
581  }
582 
583  /* Validate the buffer size. */
584  if(nBufSize == 0U)
585  {
586  return(ADI_UART_FAILED);
587  }
588 
589  /* Autobaud in progress. */
590  if(hDevice->bAutobaudInProgress == true)
591  {
592  return(ADI_UART_DEVICE_IN_USE);
593  }
594 
595  /* Make sure we are transmitting. */
596  if(ADI_UART_DIR_RECEIVE == hDevice->eDirection)
597  {
599  }
600 
601  /* Check the data transfer mode (only allowed in nonblocking mode). */
602  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
603  {
605  }
606 
607  /* Check that there is a free buffer to use for this transmit operation. pFreeBuffer
608  is the next buffer available, so if it is in use we can make the assumption that
609  there are no buffers available. The start address is set to NULL once the buffer
610  has finished being processed in "adi_uart_GetBuffer()" or "adi_uart_PendForBuffer()".
611  */
612  if(hDevice->pChannelTx->pFreeBuffer->pStartAddress != NULL)
613  {
615  }
616 
617  if(bDMA == true)
618  {
619  if(nBufSize > DMA_TRANSFER_LIMIT)
620  {
621 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
623 #endif
624  }
625 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
626  if(hDevice->pChannelTx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
627  {
628  ADI_DCC_TypeDef* pBuffer1 = pBuffer;
629 
630  /* Check if the cycle control of the descriptors is valid */
631  for(uint32_t cnt = 0u; cnt < (nBufSize-1u); cnt++)
632  {
633  if((pBuffer1[cnt].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_PSG_ALT)
634  {
636  }
637  }
638 
639  /* Validate the cycle control of the last descriptor */
640  if((pBuffer1[nBufSize-1u].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_BASIC)
641  {
643  }
644  }
645 #endif
646  }
647 
648 #endif /* ADI_DEBUG */
649 
650  /* Set the start address of the data buffer we are going to submit. */
651  hDevice->pChannelTx->pFreeBuffer->pStartAddress = pBuffer;
652 
653  /* Set the buffer size to the size of the data buffer passed down from the API. */
654  hDevice->pChannelTx->pFreeBuffer->nCount = nBufSize;
655 
656  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
657  hDevice->pChannelTx->pFreeBuffer->nRemDoneTransfers = nBufSize;
658 
659  /* Initialize the buffer index to zero because we will start shifting out
660  the Tx data from the first position of the buffer.
661  */
662  hDevice->pChannelTx->pFreeBuffer->nIndex = 0U;
663 
664  /* Mark the buffer as in use so no other transactions can use it until this one is complete. */
665  hDevice->pChannelTx->pFreeBuffer->bInUse = true;
666 
667  /* Mark the DMA as in use. */
668  hDevice->pChannelTx->pFreeBuffer->bDMA = bDMA;
669 
670  /* Initialize to select the Primary Data Control Structure */
671  hDevice->pChannelTx->bIsPrimNext = true;
672 
673  /* Set the number of free descriptors */
674  hDevice->pChannelTx->nFreeDescriptor = 2U;
675 
676  if(bDMA == true)
677  {
678  /* Initialize the DMA channel uses the primary control data structure */
679  pADI_DMA0->ALT_CLR = 1u << hDevice->pUartInfo->dmaTxChannelNum;
680 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
681  /* Set the DMA Mode to Basic */
682  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
683 #else
684 
685  /*If not previously set, configure the default DMA mode to Basic */
686  if(hDevice->pChannelTx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_INVALID)
687  {
688  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
689  }
690 
691  if (nBufSize > DMA_TRANSFER_LIMIT)
692  {
693  /* Set the mode to Ping-Pong*/
694  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PING_PONG;
695  }
696 
697  if (hDevice->pChannelTx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
698  {
699  /* Set the size of the buffer. For scatter-gather, this is the transaction size.
700  The size is multiplied by 4 since descriptors are being transferred when
701  using this mode and each descriptor is a channel control data structure that contains
702  four four-bytes members.
703  */
704  hDevice->pChannelTx->pFreeBuffer->nCount = 4u * nBufSize;
705 
706  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
707  hDevice->pChannelTx->pFreeBuffer->nRemDoneTransfers = 4u * nBufSize;
708  }
709  #endif
710  }
711  /* Now that this "pFreeBuffer" is no longer free for use, update the
712  "pFreeBuffer" to the other PingPong buffer. Because there are only two
713  buffers in the PingPong structure, this will be the opposite of the one
714  we just submitted. "pFreeBuffer" will only be updated during the process of
715  submitting a buffer or a read/write operation.
716  */
717  hDevice->pChannelTx->pFreeBuffer = hDevice->pChannelTx->pFreeBuffer->pNextBuffer;
718 
719  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE.
720  This will be set back to #ADI_UART_DATA_TRANSFER_MODE_NONE once this
721  transaction is complete. Then, if a buffer is not currently active, set up the
722  interrupts for this transaction. Otherwise if a buffer is currently active,
723  this will be taken care of in the ISR.
724  */
725  if (hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONE)
726  {
727  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING;
728  hDevice->pChannelTx->pfSubmitBuffer(hDevice, hDevice->pChannelTx->pFillBuffer);
729  }
730 
731  return(ADI_UART_SUCCESS);
732  }
733 
736 /*
737  * @brief This is an internal helper function for adi_uart_SubmitTxBuffer(). It sets up the Tx channel DMA
738  or device interrupts for the Tx channel to transmit data.
739  *
740  * @param [in] hDevice Device handle obtained from adi_uart_Open().
741  * @param [in] pBuffer Pointer to buffer from where data will be transmitted.
742  * @param [in] nBufSize Size of the buffer containing the data to be transmitted(in bytes).
743  * @param [in] bDMA Submit the buffer using the DMA.
744 */
745 static void uart_submittxbuffer(
746  ADI_UART_CONST_HANDLE const hDevice,
747  ADI_UART_BUFF_INFO *const pBuffer
748  )
749 {
750  /* If this transmission is using DMA... */
751  if (pBuffer->bDMA)
752  {
753  /* Enable clear source address decrement for TX channel DMA. */
754  pADI_DMA0->SRCADDR_CLR = 1u << (uint32_t)hDevice->pUartInfo->dmaTxChannelNum;
755 
756  /* Enable Tx channel DMA. */
757  pADI_DMA0->EN_SET = 1u << hDevice->pUartInfo->dmaTxChannelNum;
758 
759  /* Enable UART peripheral to generate DMA requests. */
760  pADI_DMA0->RMSK_CLR = 1u << hDevice->pUartInfo->dmaTxChannelNum;
762  /* Fill in the DMA RAM descriptors */
763  pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum].DMASRCEND = ((uint32_t)pBuffer->pStartAddress + (uint32_t)(pBuffer->nCount - 1u));
764 
765  pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum].DMADSTEND = (uint32_t)&hDevice->pUARTRegs->TX;
766 
767  pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum].DMACDC = ((uint32_t)ADI_DMA_INCR_NONE << DMA_BITP_CTL_DST_INC) |
768  ((uint32_t)ADI_DMA_INCR_1_BYTE << DMA_BITP_CTL_SRC_INC) |
769  (ADI_DMA_WIDTH_1_BYTE << DMA_BITP_CTL_SRC_SIZE) |
770  (0u << DMA_BITP_CTL_R_POWER) |
771  ((pBuffer->nCount - 1u) << DMA_BITP_CTL_N_MINUS_1) |
772  (DMA_ENUM_CTL_CYCLE_CTL_BASIC << DMA_BITP_CTL_CYCLE_CTL);
773 
774 #else
775  /* Pointer to the Channel Control Data Structure. */
776  ADI_DCC_TypeDef* pCCD;
777 
778  /* Pointer to the Uart Data Channel. */
779  ADI_UART_DATA_CHANNEL* pChannel = hDevice->pChannelTx;
780 
781  /* Number of bytes to be processed. */
782  uint16_t nTransactions = 0;
783 
784  /* Variable that holds the control data configuration. */
785  uint32_t nCfg = 0;
786 
787  /* Source address increment. */
788  uint32_t srcInc = 0;
789 
790  /* Destination address increment. */
791  uint32_t dstAddr = 0;
792 
793  while(pBuffer->nCount > 0 && pChannel->nFreeDescriptor > 0)
794  {
795  if(pBuffer->nCount < 2*DMA_TRANSFER_LIMIT)
796  {
797  if(pBuffer->nCount > DMA_TRANSFER_LIMIT)
798  {
799  nTransactions = pBuffer->nCount/2;
800  }
801  else
802  {
803  nTransactions = pBuffer->nCount;
804  }
805  }
806  else
807  {
808  nTransactions = DMA_TRANSFER_LIMIT;
809  }
810 
811  if (pChannel->bIsPrimNext)
812  {
813  /* Set the CCD pointer to point to the Primary Data Structure */
814  pCCD = &pPrimaryCCD[hDevice->pUartInfo->dmaTxChannelNum];
815  pChannel->bIsPrimNext = false;
816  }
817  else
818  {
819  /* Set the CCD pointer to point to the Alternate Data Structure */
820  pCCD = &pAlternateCCD[hDevice->pUartInfo->dmaTxChannelNum];
821  pChannel->bIsPrimNext = true;
822  }
823 
824  /* Decrement the number of available descriptors */
825  pChannel->nFreeDescriptor--;
826 
827  if (pBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
828  {
829  nCfg = ((uint32_t)ADI_DMA_INCR_4_BYTE << DMA_BITP_CTL_DST_INC) |
830  ((uint32_t)ADI_DMA_INCR_4_BYTE << DMA_BITP_CTL_SRC_INC) |
831  (ADI_DMA_WIDTH_4_BYTE << DMA_BITP_CTL_SRC_SIZE) |
832  (ADI_DMA_RPOWER_4 << DMA_BITP_CTL_R_POWER) |
833  ((nTransactions-1) << DMA_BITP_CTL_N_MINUS_1) |
834  (pBuffer->nDmaMode<< DMA_BITP_CTL_CYCLE_CTL);
835 
836  dstAddr = (uint32_t)&pAlternateCCD[hDevice->pUartInfo->dmaTxChannelNum].RESERVED;
837  }
838 
839  else
840  {
841  nCfg = ((uint32_t)ADI_DMA_INCR_NONE << DMA_BITP_CTL_DST_INC) |
842  ((uint32_t)ADI_DMA_INCR_1_BYTE << DMA_BITP_CTL_SRC_INC) |
843  (ADI_DMA_WIDTH_1_BYTE << DMA_BITP_CTL_SRC_SIZE) |
844  (ADI_DMA_RPOWER_1 << DMA_BITP_CTL_R_POWER) |
845  ((nTransactions-1) << DMA_BITP_CTL_N_MINUS_1) |
846  (pBuffer->nDmaMode<< DMA_BITP_CTL_CYCLE_CTL);
847 
848  dstAddr = (uint32_t)&hDevice->pUARTRegs->TX;
849 
850  }
851 
852  /* Retrieve the source increment */
853  srcInc = 1u << ((nCfg & DMA_BITM_CTL_SRC_INC) >> DMA_BITP_CTL_SRC_INC);
854 
855  /* Fill in the DMA descriptors */
856  pCCD->DMASRCEND = (uint32_t)pBuffer->pStartAddress + ((nTransactions-1) + pBuffer->nIndex) * srcInc;
857 
858  pCCD->DMADSTEND = dstAddr;
859 
860  pCCD->DMACDC = nCfg;
861 
862  /* Update the nCount and nIndex */
863  pBuffer->nCount -= nTransactions;
864  pBuffer->nIndex += nTransactions;
865  }
866 #endif
867 
868  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
869  also doesn't modify the same register concurrently */
870  ADI_INT_STATUS_ALLOC();
871  ADI_ENTER_CRITICAL_REGION();
872  /* Enable UART DMA request interrupt for the Tx channel. */
873  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_EDMAT);
874  ADI_EXIT_CRITICAL_REGION();
875  }
876  else
877  /* If this transmission is using UART interrupts.. */
878  {
879  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
880  also doesn't modify the same register concurrently */
881  ADI_INT_STATUS_ALLOC();
882  ADI_ENTER_CRITICAL_REGION();
883  /* Enable buffer empty interrupts. */
884  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_ETBEI);
885  ADI_EXIT_CRITICAL_REGION();
886  }
887 }
888 
924  ADI_UART_HANDLE const hDevice,
925  void *const pBuffer,
926  uint32_t const nBufSize,
927  bool const bDMA
928  )
929 {
930 
931 #ifdef ADI_DEBUG
932  /* Validate the device handle. */
933  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
934  {
935  return(ADI_UART_INVALID_HANDLE);
936  }
937 
938  /* Validate the pointer to the buffer memory. */
939  if(pBuffer == NULL)
940  {
941  return(ADI_UART_INVALID_POINTER);
942  }
943 
944  /* Validate the buffer size. */
945  if(nBufSize == 0U )
946  {
947  return(ADI_UART_FAILED);
948  }
949 
950  /* Autobaud in progress. */
951  if(hDevice->bAutobaudInProgress == true)
952  {
953  return(ADI_UART_DEVICE_IN_USE);
954  }
955 
956  /* Make sure the UART device is configured to operate in the receive direction. */
957  if(ADI_UART_DIR_TRANSMIT == hDevice->eDirection)
958  {
960  }
961 
962  /* Check for the data transfer mode(only allowed in nonblocking mode). */
963  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
964  {
966  }
967 
968  /* Check that there is a free buffer to use for this operation. pFreeBuffer
969  is the next buffer available, so if it is in use we can make the assumption that
970  there are no buffers available. If the start address is not set to NULL, then we
971  can conclude the buffer has not finished being processed because this gets set in
972  adi_uart_pend_for_buffer() and adi_uart_get_buffer().
973  */
974  if(hDevice->pChannelRx->pFreeBuffer->pStartAddress != NULL)
975  {
977  }
978 
979  /* Set the DMA mode to Ping Pong if the DMA transfer size exceeds the maximum transfer
980  limit. */
981  if(bDMA == true)
982  {
983  if(nBufSize > DMA_TRANSFER_LIMIT)
984  {
985 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
987 #endif
988  }
989 
990 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
991  if(hDevice->pChannelRx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
992  {
993  ADI_DCC_TypeDef* pBuffer1 = pBuffer;
994 
995  /* Check if the cycle control of the descriptors is valid */
996  for(uint32_t cnt = 0u; cnt < (nBufSize-1u); cnt++)
997  {
998  if((pBuffer1[cnt].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_PSG_ALT)
999  {
1001  }
1002  }
1003 
1004  /* Validate the cycle control of the last descriptor */
1005  if((pBuffer1[nBufSize-1u].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_BASIC)
1006  {
1008  }
1009  }
1010 #endif
1011  }
1012 
1013 
1014 
1015 #endif /* ADI_DEBUG */
1016 
1017  /* Set the start address of the buffer you are going to submit. */
1018  hDevice->pChannelRx->pFreeBuffer->pStartAddress = pBuffer;
1019 
1020  /* Set the size of the buffer. */
1021  hDevice->pChannelRx->pFreeBuffer->nCount = nBufSize;
1022 
1023  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
1024  hDevice->pChannelRx->pFreeBuffer->nRemDoneTransfers = nBufSize;
1025 
1026  /* Initialize the buffer index to 0, because as we receive data it will be put into
1027  the buffer starting at the first position.
1028  */
1029  hDevice->pChannelRx->pFreeBuffer->nIndex = 0U;
1030 
1031  /* Mark the buffer as in use. */
1032  hDevice->pChannelRx->pFreeBuffer->bInUse = true;
1033 
1034  /* Mark the DMA as in use. */
1035  hDevice->pChannelRx->pFreeBuffer->bDMA = bDMA;
1036 
1037  /* Initialize to select the Primary Data Control Structure */
1038  hDevice->pChannelRx->bIsPrimNext = true;
1039 
1040  /* Set the number of free descriptors */
1041  hDevice->pChannelRx->nFreeDescriptor = 2;
1042 
1043  if(bDMA == true)
1044  {
1045  /* Initialize the DMA channel uses the primary control data structure */
1046  pADI_DMA0->ALT_CLR = 1u << hDevice->pUartInfo->dmaRxChannelNum;
1047 
1048 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
1049  /* Set the DMA Mode to Basic */
1050  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
1051 #else
1052  /*If not previously set, configure the default DMA mode to Basic */
1053  if(hDevice->pChannelRx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_INVALID)
1054  {
1055  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
1056  }
1057 
1058  if(nBufSize > DMA_TRANSFER_LIMIT)
1059  {
1060  /* Set the mode to Ping-Pong*/
1061  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PING_PONG;
1062  }
1063 
1064  if(hDevice->pChannelRx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
1065  {
1066  /* Set the size of the buffer. For scatter-gather, this is the transaction size.
1067  The size is multiplied by 4 since descriptors are being transferred when
1068  using this mode and each descriptor is a channel control data structure that contains
1069  four four-bytes members.
1070  */
1071  hDevice->pChannelRx->pFreeBuffer->nCount = 4u * nBufSize;
1072 
1073  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
1074  hDevice->pChannelRx->pFreeBuffer->nRemDoneTransfers = 4u * nBufSize;
1075  }
1076 #endif
1077  }
1078  /* Now that this "pFreeBuffer" is no longer free for use, update the
1079  "pFreeBuffer" to the other PingPong buffer. Because there are only two
1080  buffers in the PingPong structure, this will be the opposite of the one
1081  we just submitted. "pFreeBuffer" will only be updated during the process of
1082  submitting a buffer or a read/write operation.
1083  */
1084  hDevice->pChannelRx->pFreeBuffer = hDevice->pChannelRx->pFreeBuffer->pNextBuffer;
1085 
1086 
1087  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE.
1088  This will be set back to #ADI_UART_DATA_TRANSFER_MODE_NONE once this
1089  transaction is complete. Then, if a buffer is not currently active, set up the
1090  interrupts for this transaction. Otherwise if a buffer is currently active,
1091  this will be taken care of in the ISR.
1092  */
1093  if (hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONE)
1094  {
1095  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING;
1096  hDevice->pChannelRx->pfSubmitBuffer(hDevice, hDevice->pChannelRx->pFillBuffer);
1097  }
1098 
1099  return(ADI_UART_SUCCESS);
1100 }
1101 
1104 /*
1105  * @brief This is an internal helper function for adi_uart_SubmitRxBuffer(). It sets up the DMA
1106  * or device receive interrupts for the Rx channel to receive data.
1107  *
1108  * @param [in] hDevice Device handle obtained from adi_uart_Open().
1109  * @param [in] pBuffer Pointer to the empty receive buffer.
1110  * @param [in] nBufSize Size of the receive buffer(in bytes).
1111  * @param [in] bDMA Submit the buffer using the DMA.
1112 */
1113 static void uart_submitrxbuffer(
1114  ADI_UART_CONST_HANDLE const hDevice,
1115  ADI_UART_BUFF_INFO *const pBuffer
1116  )
1117 {
1118  /* If this transaction is using the DMA.. */
1119  if (pBuffer->bDMA)
1120  {
1121  /* Enable source address decrement for RX DMA channel. */
1122  pADI_DMA0->DSTADDR_CLR = 1u << (uint32_t)hDevice->pUartInfo->dmaRxChannelNum;
1123 
1124  /* Enable Rx DMA channel. */
1125  pADI_DMA0->EN_SET = 1u << hDevice->pUartInfo->dmaRxChannelNum;
1126 
1127  /* Enable UART peripheral to generate DMA requests. */
1128  pADI_DMA0->RMSK_CLR = 1u << hDevice->pUartInfo->dmaRxChannelNum;
1129 
1131  /* Fill in the DMA RAM descriptors. */
1132  pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum].DMASRCEND = (uint32_t)&hDevice->pUARTRegs->RX;
1133 
1134  pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum].DMADSTEND = ((uint32_t)pBuffer->pStartAddress + (uint32_t)(pBuffer->nCount - 1u));
1135 
1136  pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum].DMACDC = (uint32_t)(ADI_DMA_INCR_1_BYTE << DMA_BITP_CTL_DST_INC) |
1137  (uint32_t)(ADI_DMA_INCR_NONE << DMA_BITP_CTL_SRC_INC) |
1138  (ADI_DMA_WIDTH_1_BYTE << DMA_BITP_CTL_SRC_SIZE) |
1139  (0u << DMA_BITP_CTL_R_POWER) |
1140  ((pBuffer->nCount - 1u) << DMA_BITP_CTL_N_MINUS_1) |
1141  (DMA_ENUM_CTL_CYCLE_CTL_BASIC << DMA_BITP_CTL_CYCLE_CTL);
1142 #else
1143  /* Pointer to the Channel Control Data Structure. */
1144  ADI_DCC_TypeDef* pCCD;
1145 
1146  /* Pointer to the Uart Rx Data Channel. */
1147  ADI_UART_DATA_CHANNEL* pChannel = hDevice->pChannelRx;
1148 
1149  /* Number of bytes to be processed. */
1150  uint16_t nTransactions = 0;
1151 
1152  /* Variable that holds the control data configuration. */
1153  uint32_t nCfg = 0;
1154 
1155  /* Source address increment. */
1156  uint32_t srcInc = 0;
1157 
1158  /* Destination address increment. */
1159  uint32_t dstInc = 0;
1160 
1161  /* Destination end address. */
1162  uint32_t dstAddr = 0;
1163 
1164  /* Source end address. */
1165  uint32_t srcAddr = 0;
1166 
1167  while (pBuffer->nCount > 0 && pChannel->nFreeDescriptor > 0)
1168  {
1169  if(pBuffer->nCount < 2*DMA_TRANSFER_LIMIT)
1170  {
1171  if(pBuffer->nCount > DMA_TRANSFER_LIMIT)
1172  {
1173  nTransactions = pBuffer->nCount/2;
1174  }
1175  else
1176  {
1177  nTransactions = pBuffer->nCount;
1178  }
1179  }
1180  else
1181  {
1182  nTransactions = DMA_TRANSFER_LIMIT;
1183  }
1184 
1185  if(pChannel->bIsPrimNext)
1186  {
1187  /* Set the CCD pointer to point to the Primary Data Structure */
1188  pCCD= &pPrimaryCCD[hDevice->pUartInfo->dmaRxChannelNum];
1189  pChannel->bIsPrimNext = false;
1190  }
1191  else
1192  {
1193  /* Set the CCD pointer to point to the Alternate Data Structure */
1194  pCCD= &pAlternateCCD[hDevice->pUartInfo->dmaRxChannelNum];
1195  pChannel->bIsPrimNext = true;
1196  }
1197 
1198  /* Decrement the number of available descriptors */
1199  pChannel->nFreeDescriptor--;
1200 
1201  if (pBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
1202  {
1203  nCfg = ((uint32_t)ADI_DMA_INCR_4_BYTE << DMA_BITP_CTL_DST_INC) |
1204  ((uint32_t)ADI_DMA_INCR_4_BYTE << DMA_BITP_CTL_SRC_INC) |
1205  (ADI_DMA_WIDTH_4_BYTE << DMA_BITP_CTL_SRC_SIZE) |
1206  (ADI_DMA_RPOWER_4 << DMA_BITP_CTL_R_POWER) |
1207  ((nTransactions-1) << DMA_BITP_CTL_N_MINUS_1) |
1208  (pBuffer->nDmaMode<< DMA_BITP_CTL_CYCLE_CTL);
1209 
1210  /* Retrieve the src increment */
1211  srcInc = 1u << ((nCfg & DMA_BITM_CTL_SRC_INC) >> DMA_BITP_CTL_SRC_INC);
1212 
1213  srcAddr = (uint32_t)pBuffer->pStartAddress + ((nTransactions-1) + pBuffer->nIndex) * srcInc;
1214  dstAddr = (uint32_t)&pAlternateCCD[hDevice->pUartInfo->dmaRxChannelNum].RESERVED;
1215  }
1216 
1217  else
1218  {
1219 
1220  nCfg = ((uint32_t)ADI_DMA_INCR_1_BYTE << DMA_BITP_CTL_DST_INC) |
1221  ((uint32_t)ADI_DMA_INCR_NONE << DMA_BITP_CTL_SRC_INC) |
1222  (ADI_DMA_WIDTH_1_BYTE << DMA_BITP_CTL_SRC_SIZE) |
1223  (ADI_DMA_RPOWER_1 << DMA_BITP_CTL_R_POWER) |
1224  ((nTransactions-1) << DMA_BITP_CTL_N_MINUS_1) |
1225  (pBuffer->nDmaMode<< DMA_BITP_CTL_CYCLE_CTL);
1226 
1227  /* Retrieve the dst increment */
1228  dstInc = 1u << ((nCfg & DMA_BITM_CTL_DST_INC) >> DMA_BITP_CTL_DST_INC);
1229 
1230  srcAddr = (uint32_t)&hDevice->pUARTRegs->RX;
1231  dstAddr = (uint32_t)pBuffer->pStartAddress + ((nTransactions-1) + pBuffer->nIndex) * dstInc;
1232 
1233  }
1234 
1235  /* Fill in the DMA RAM descriptors. */
1236  pCCD->DMASRCEND = srcAddr;
1237 
1238  pCCD->DMADSTEND = dstAddr;
1239 
1240  pCCD->DMACDC = nCfg;
1241 
1242  /* Update the nCount and nIndex */
1243  pBuffer->nCount -= nTransactions;
1244  pBuffer->nIndex += nTransactions;
1245  }
1246 #endif
1247  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
1248  also doesn't modify the same register concurrently */
1249  ADI_INT_STATUS_ALLOC();
1250  ADI_ENTER_CRITICAL_REGION();
1251  /* Enable UART receive DMA requests. */
1252  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_EDMAR);
1253  ADI_EXIT_CRITICAL_REGION();
1254  }
1255  /* If this transaction is using UART interrupts.. */
1256  else
1257  {
1258  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
1259  also doesn't modify the same register concurrently */
1260  ADI_INT_STATUS_ALLOC();
1261  ADI_ENTER_CRITICAL_REGION();
1262  /* Enable buffer full interrupt. */
1263  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_ERBFI);
1264  ADI_EXIT_CRITICAL_REGION();
1265  }
1266 }
1267 
1295  ADI_UART_HANDLE const hDevice,
1296  void **const ppBuffer,
1297  uint32_t *pHwError
1298  )
1299 
1300 {
1301 
1302 #ifdef ADI_DEBUG
1303  /* Validate the device handle. */
1304  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1305  {
1306  return(ADI_UART_INVALID_HANDLE);
1307  }
1308 
1309  /* Validate that this buffer has actually been submitted. */
1310  if(hDevice->pChannelTx->pActiveBuffer->pStartAddress == NULL)
1311  {
1313  }
1314 
1315  /* This function is allowed to be called when the channel is operating in NONBLOCKING mode. */
1316  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
1317  {
1319  }
1320 #endif /* ADI_DEBUG */
1321 
1322  /* Blocking call to get the submitted buffer */
1323  return(uart_getbuffer(hDevice, hDevice->pChannelTx, ppBuffer, pHwError));
1324 }
1325 
1326 
1327 
1353  ADI_UART_HANDLE const hDevice,
1354  void **const ppBuffer,
1355  uint32_t *pHwError
1356  )
1357 
1358 {
1359 
1360 #ifdef ADI_DEBUG
1361  /* Validate the device handle. */
1362  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1363  {
1364  return(ADI_UART_INVALID_HANDLE);
1365  }
1366 
1367  /* Validate that this buffer has actually been submitted. */
1368  if(hDevice->pChannelRx->pActiveBuffer->pStartAddress == NULL)
1369  {
1371  }
1372 
1373  /* This function is only allowed to be called when the channel is operating in NONBLOCKING mode. */
1374  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
1375  {
1377  }
1378 #endif /* ADI_DEBUG */
1379 
1380  /* Blocking call to get the full Rx Buffer */
1381  return(uart_getbuffer(hDevice, hDevice->pChannelRx, ppBuffer, pHwError));
1382 }
1383 
1386 /*
1387  * @brief This is an internal helper function for adi_uart_GetRxBuffer() and adi_uart_GetTxBuffer().
1388  * It blocks until until the completion of the data transaction.
1389  *
1390  * @param [in] hDevice Device handle obtained from adi_uart_Open().
1391  * @param [in] pChannel Pointer to UART channel data structure.
1392  * @param [out] ppBuffer Contains the address of the buffer passed down from the API.
1393  * @param [out] pHwError Pointer to an integer that correlates with #ADI_UART_HW_ERRORS, containg the hardware status.
1394  * If there is no hardware event, this will be 0.
1395  *
1396  * @return Status
1397  * - #ADI_UART_SUCCESS Successfully got buffer.
1398  * - #ADI_UART_HW_ERROR_DETECTED Hardware error(s) detected. "pHwError" can be checked for the specific error code(s).
1399  *
1400 */
1401 static ADI_UART_RESULT uart_getbuffer(
1402  ADI_UART_HANDLE hDevice,
1403  ADI_UART_DATA_CHANNEL *pChannel,
1404  void **ppBuffer,
1405  uint32_t *pHwError
1406  )
1407 {
1408  /* Set ppBuffer to NULL in case there is an error. */
1409  *ppBuffer = NULL;
1410 
1411  /* Wait until the peripheral has finished processing the buffer. */
1412  SEM_PEND(pChannel,ADI_UART_FAILED);
1413 
1414  /* Save the address of the buffer that has just been processed, so it can be
1415  returned back to the API.
1416  */
1417  *ppBuffer = pChannel->pActiveBuffer->pStartAddress;
1418 
1419  /* Reinitialize the start address to NULL so this buffer can be used for a new transaction. */
1420  pChannel->pActiveBuffer->pStartAddress = NULL;
1421 
1422  /* Now that the desired data has either been transmitted or received, this buffer is no longer
1423  in use. We can update "pActiveBuffer" to point to the next buffer that will become or is already
1424  active.
1425  */
1426  pChannel->pActiveBuffer = pChannel->pActiveBuffer->pNextBuffer;
1427 
1428  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
1429  This will only be done if there are no other active buffers in flight to avoid disrupting an active transfer.
1430  */
1431  if(pChannel->pActiveBuffer->pStartAddress == NULL)
1432  {
1433  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
1434  }
1435 
1436  /* If there are hardware errors and no callback, then return failure. */
1437  if(hDevice->nHwError != 0u)
1438  {
1439  /* Save the hardware error detected. This will be passed back to the API. */
1440  *pHwError = hDevice->nHwError;
1441 
1442  /* Clear any hardware errors detected. */
1443  hDevice->nHwError = 0u;
1444 
1446  }
1447  else
1448  {
1449  return(ADI_UART_SUCCESS);
1450  }
1451 }
1452 
1491  ADI_UART_HANDLE const hDevice,
1492  void *const pBuffer,
1493  uint32_t const nBufSize,
1494  bool const bDMA,
1495  uint32_t *pHwError
1496  )
1497 {
1498 
1499 #ifdef ADI_DEBUG
1500  /* Validate the given handle. */
1501  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1502  {
1503  return(ADI_UART_INVALID_HANDLE);
1504  }
1505 
1506  /* Validate the pointer to the buffer memory. */
1507  if(pBuffer == NULL)
1508  {
1509  return(ADI_UART_INVALID_POINTER);
1510  }
1511 
1512  /* Validate the buffer size. */
1513  if(nBufSize == 0U )
1514  {
1515  return(ADI_UART_FAILED);
1516  }
1517 
1518  /* Autobaud in progress. */
1519  if(hDevice->bAutobaudInProgress == true)
1520  {
1521  return(ADI_UART_DEVICE_IN_USE);
1522  }
1523 
1524  /* Make sure we are transmitting. */
1525  if(ADI_UART_DIR_RECEIVE == hDevice->eDirection)
1526  {
1528  }
1529 
1530  /* Check for the data transfer mode (only allowed in blocking mode). */
1531  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING)
1532  {
1534  }
1535 
1536  /* Check that there is a free buffer to use for this transmit operation. "pFreeBuffer"
1537  is the next buffer available, so if it is in use we can make the assumption that
1538  there are no buffers available. The start address is set to NULL once the buffer
1539  has been processed.
1540  */
1541  if(hDevice->pChannelTx->pFreeBuffer->pStartAddress != NULL)
1542  {
1544  }
1545 
1546  if(bDMA == true)
1547  {
1548  if(nBufSize > DMA_TRANSFER_LIMIT)
1549  {
1550 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
1552 #endif
1553  }
1554 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) || (ADI_UART_DMA_EXTENSION_ENABLE == 1)
1555  if(hDevice->pChannelTx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
1556  {
1557  ADI_DCC_TypeDef* pBuffer1 = pBuffer;
1558 
1559  /* Check if the cycle control of the descriptors is valid */
1560  for(uint32_t cnt = 0u; cnt < (nBufSize-1u); cnt++)
1561  {
1562  if((pBuffer1[cnt].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_PSG_ALT)
1563  {
1565  }
1566  }
1567 
1568  /* Validate the cycle control of the last descriptor */
1569  if((pBuffer1[nBufSize-1u].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_BASIC)
1570  {
1572  }
1573  }
1574 #endif
1575  }
1576 
1577 #endif /* ADI_DEBUG */
1578 
1579  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE. */
1580  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_BLOCKING;
1581 
1582  /* Set the start address of the data buffer we are going to submit. */
1583  hDevice->pChannelTx->pFreeBuffer->pStartAddress = pBuffer;
1584 
1585  /* Set the buffer size to the size of the data buffer passed down from the API. */
1586  hDevice->pChannelTx->pFreeBuffer->nCount = nBufSize;
1587 
1588  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
1589  hDevice->pChannelTx->pFreeBuffer->nRemDoneTransfers = nBufSize;
1590 
1591  /* Initialize the buffer index to zero because we will start shifting out
1592  the Tx data from the first position of the buffer.
1593  */
1594  hDevice->pChannelTx->pFreeBuffer->nIndex = 0U;
1595 
1596  /* Mark the buffer as in use so no other transactions can use it until this one is complete. */
1597  hDevice->pChannelTx->pFreeBuffer->bInUse = true;
1598 
1599  /* Mark the DMA as in use. */
1600  hDevice->pChannelTx->pFreeBuffer->bDMA = bDMA;
1601 
1602  /* Initialize to select the Primary Data Control Structure */
1603  hDevice->pChannelTx->bIsPrimNext = true;
1604 
1605  /* Set the number of free descriptors */
1606  hDevice->pChannelTx->nFreeDescriptor = 2U;
1607 
1608  if(bDMA == true)
1609  {
1610  /* Initialize the DMA channel uses the primary control data structure */
1611  pADI_DMA0->ALT_CLR = 1u << hDevice->pUartInfo->dmaTxChannelNum;
1612 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
1613  /* Set the DMA Mode to Basic */
1614  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
1615 #else
1616  /*If not previously set, configure the default DMA mode to Basic */
1617  if(hDevice->pChannelTx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_INVALID)
1618  {
1619  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
1620  }
1621  if (nBufSize > DMA_TRANSFER_LIMIT)
1622  {
1623  /* Set the mode to Ping-Pong*/
1624  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PING_PONG;
1625  }
1626 
1627  if (hDevice->pChannelTx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
1628  {
1629  /* Set the size of the buffer. For scatter-gather, this is the transaction size.
1630  The size is multiplied by 4 since descriptors are being transferred when
1631  using this mode and each descriptor is a channel control data structure that contains
1632  four four-bytes members.
1633  */
1634  hDevice->pChannelTx->pFreeBuffer->nCount = 4u * nBufSize;
1635 
1636  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
1637  hDevice->pChannelTx->pFreeBuffer->nRemDoneTransfers = 4u * nBufSize;
1638  }
1639 #endif
1640  }
1641 
1642  /* Now that this "pFreeBuffer" is no longer free for use, update the
1643  "pFreeBuffer" to the other PingPong buffer. Because there are only two
1644  buffers in the PingPong structure, this will be the opposite of the one
1645  we just submitted. "pFreeBuffer" will only be updated during the process of
1646  submitting a buffer or a read/write operation.
1647  */
1648  hDevice->pChannelTx->pFreeBuffer = hDevice->pChannelTx->pFreeBuffer->pNextBuffer;
1649 
1650  hDevice->pChannelTx->pfSubmitBuffer(hDevice, hDevice->pChannelTx->pFillBuffer);
1651 
1652  /* Block for the active buffer to complete. */
1653  return(uart_PendForBuffer(hDevice, hDevice->pChannelTx, pHwError));
1654 }
1655 
1691  ADI_UART_HANDLE const hDevice,
1692  void *const pBuffer,
1693  uint32_t const nBufSize,
1694  bool const bDMA,
1695  uint32_t *pHwError
1696  )
1697 {
1698 
1699 #ifdef ADI_DEBUG
1700  /* Validate the given handle. */
1701  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1702  {
1703  return(ADI_UART_INVALID_HANDLE);
1704  }
1705 
1706  /* Validate the pointer to the buffer memory. */
1707  if(pBuffer == NULL)
1708  {
1709  return(ADI_UART_INVALID_POINTER);
1710  }
1711 
1712  /* Validate the buffer size. */
1713  if(nBufSize == 0U )
1714  {
1715  return(ADI_UART_FAILED);
1716  }
1717 
1718  /* Autobaud in progress. */
1719  if(hDevice->bAutobaudInProgress == true)
1720  {
1721  return(ADI_UART_DEVICE_IN_USE);
1722  }
1723 
1724  /* Make sure the UART device is configured to operate in the receive direction. */
1725  if(ADI_UART_DIR_TRANSMIT == hDevice->eDirection)
1726  {
1728  }
1729 
1730  /* Check for the data transfer mode(only allowed in blocking mode).*/
1731  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING)
1732  {
1734  }
1735 
1736  /* Check that there is a free buffer to use for this receive operation. "pFreeBuffer"
1737  is the next buffer available, so if it is in use we can make the assumption that
1738  there are no buffers available. The start address gets set to NULL once the buffer
1739  processing has completed.
1740  */
1741  if(hDevice->pChannelRx->pFreeBuffer->pStartAddress != NULL)
1742  {
1744  }
1745 
1746  if(bDMA == true)
1747  {
1748  if(nBufSize > DMA_TRANSFER_LIMIT)
1749  {
1750 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
1752 #endif
1753  }
1754 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
1755  if(hDevice->pChannelRx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
1756  {
1757  ADI_DCC_TypeDef* pBuffer1 = pBuffer;
1758 
1759  /* Check if the cycle control of the descriptors is valid */
1760  for(uint32_t cnt = 0u; cnt < (nBufSize-1u); cnt++)
1761  {
1762  if((pBuffer1[cnt].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_PSG_ALT)
1763  {
1765  }
1766  }
1767 
1768  /* Validate the cycle control of the last descriptor */
1769  if((pBuffer1[nBufSize-1u].DMACDC & DMA_BITM_CTL_CYCLE_CTL) != DMA_ENUM_CTL_CYCLE_CTL_BASIC)
1770  {
1772  }
1773  }
1774 #endif
1775  }
1776 
1777 
1778 
1779 #endif /* ADI_DEBUG */
1780 
1781  /* Set the data transfer mode in case it was #ADI_UART_DATA_TRANSFER_MODE_NONE.
1782  This will be set back to #ADI_UART_DATA_TRANSFER_MODE_NONE once this
1783  transaction is complete.
1784  */
1785  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_BLOCKING;
1786 
1787  /* Set the start address of the buffer you are going to submit. */
1788  hDevice->pChannelRx->pFreeBuffer->pStartAddress = pBuffer;
1789 
1790  /* Set the size of the buffer. */
1791  hDevice->pChannelRx->pFreeBuffer->nCount = nBufSize;
1792 
1793  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
1794  hDevice->pChannelRx->pFreeBuffer->nRemDoneTransfers = nBufSize;
1795 
1796  /* Initialize the buffer index to 0, because as we receive data it will be put into
1797  the buffer starting at the first position.
1798  */
1799  hDevice->pChannelRx->pFreeBuffer->nIndex = 0U;
1800 
1801  /* Mark the buffer as in use. */
1802  hDevice->pChannelRx->pFreeBuffer->bInUse = true;
1803 
1804  /* Mark the DMA as in use. */
1805  hDevice->pChannelRx->pFreeBuffer->bDMA = bDMA;
1806 
1807  /* Initialize to select the Primary Data Control Structure */
1808  hDevice->pChannelRx->bIsPrimNext = true;
1809 
1810  /* Set the number of free descriptors */
1811  hDevice->pChannelRx->nFreeDescriptor = 2;
1812 
1813  if(bDMA == true)
1814  {
1815  /*Initialize the DMA channel uses the primary control data structure */
1816  pADI_DMA0->ALT_CLR = 1u << hDevice->pUartInfo->dmaRxChannelNum;
1817 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
1818  /* Set the DMA Mode to Basic */
1819  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
1820 #else
1821  /*If not previously set, configure the default DMA mode to Basic */
1822  if(hDevice->pChannelRx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_INVALID)
1823  {
1824  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
1825  }
1826 
1827  if(nBufSize > DMA_TRANSFER_LIMIT)
1828  {
1829  /* Set the mode to Ping-Pong*/
1830  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PING_PONG;
1831  }
1832  if(hDevice->pChannelRx->pFreeBuffer->nDmaMode == DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI)
1833  {
1834  /* Set the size of the buffer. For scatter-gather, this is the transaction size.
1835  The size is multiplied by 4 since descriptors are being transferred when
1836  using this mode and each descriptor is a channel control data structure that contains
1837  four four-bytes members.
1838  */
1839  hDevice->pChannelRx->pFreeBuffer->nCount = 4u * nBufSize;
1840 
1841  /* Initialize the value of nRemDoneTransfers with the size of the buffer */
1842  hDevice->pChannelRx->pFreeBuffer->nRemDoneTransfers = 4u * nBufSize;
1843  }
1844 #endif
1845  }
1846 
1847 
1848  /* Now that this "pFreeBuffer" is no longer free for use, update the
1849  "pFreeBuffer" to the other PingPong buffer. Because there are only two
1850  buffers in the PingPong structure, this will be the opposite of the one
1851  we just submitted. "pFreeBuffer" will only be updated during the process of
1852  submitting a buffer or a read/write operation.
1853  */
1854  hDevice->pChannelRx->pFreeBuffer = hDevice->pChannelRx->pFreeBuffer->pNextBuffer;
1855 
1856  hDevice->pChannelRx->pfSubmitBuffer(hDevice, hDevice->pChannelRx->pFillBuffer);
1857 
1858  /* Block for the active buffer to complete. */
1859  return(uart_PendForBuffer(hDevice, hDevice->pChannelRx, pHwError));
1860 }
1861 
1879  ADI_UART_HANDLE const hDevice,
1880  uint8_t *const pRX
1881  )
1882 {
1883 
1884 #ifdef ADI_DEBUG
1885  /* Validate the given handle. */
1886  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
1887  {
1888  return(ADI_UART_INVALID_HANDLE);
1889  }
1890 
1891  /* Validate the pointer to data. */
1892  if(pRX == NULL)
1893  {
1894  return(ADI_UART_INVALID_POINTER);
1895  }
1896 
1897  /* Autobaud in progress. */
1898  if(hDevice->bAutobaudInProgress == true)
1899  {
1900  return(ADI_UART_DEVICE_IN_USE);
1901  }
1902 
1903  /* Make sure the UART device is configured to operate in the receive direction. */
1904  if(ADI_UART_DIR_TRANSMIT == hDevice->eDirection)
1905  {
1907  }
1908 
1909  /* Check for the data transfer mode(only allowed in blocking mode).*/
1910  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING)
1911  {
1913  }
1914 #endif /* ADI_DEBUG */
1915 
1916  *pRX = hDevice->pUARTRegs->RX;
1917  return(ADI_UART_SUCCESS);
1918 }
1919 
1922 /*
1923  * @brief Pends for data transaction to complete. Buffer gets returned to API.
1924  *
1925  * @param [in] hDevice Device handle obtained from adi_uart_Open().
1926  * @param [in] pChannel Pointer to UART channel data structure.
1927  * @param [out] pBuffer Address of buffer on which data transfer being carried out.
1928  * @param [out] pHwError Pointer to an integer that correlates with #ADI_UART_HW_ERRORS, containg the hardware status.
1929  * If there is no hardware event, this will be 0.
1930  *
1931  * @return Status
1932  * - #ADI_UART_SUCCESS Successfully got buffer.
1933  * - #ADI_UART_HW_ERROR_DETECTED Hardware error(s) detected. "pHwError" can be checked for the specific error code(s).
1934  *
1935 */
1936 static ADI_UART_RESULT uart_PendForBuffer(
1937  ADI_UART_HANDLE const hDevice,
1938  ADI_UART_DATA_CHANNEL *pChannel,
1939  uint32_t *pHwError
1940  )
1941 {
1942 
1943  /* Wait until the peripheral has finished processing the buffer. */
1944  SEM_PEND(pChannel,ADI_UART_FAILED);
1945 
1946  /* Reinitialize the start address to NULL so this buffer can be used for a new transaction. */
1947  pChannel->pActiveBuffer->pStartAddress = NULL;
1948 
1949  /* Now that the desired data has either been transmitted or received, this buffer is no longer
1950  in use. We can update "pActiveBuffer" to point to the next buffer that will become or is already
1951  active. This will only be updated in places where transactions are completed,
1952  such as uart_PendForBuffer() and uart_GetBuffer().
1953  */
1954  pChannel->pActiveBuffer = pChannel->pActiveBuffer->pNextBuffer;
1955 
1956  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
1957  Only if there are no active buffers.
1958  */
1959  if(pChannel->pActiveBuffer->pStartAddress == NULL)
1960  {
1961  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
1962  }
1963 
1964  /* If there are hardware errors and no callback, then return failure. */
1965  if(hDevice->nHwError != 0u)
1966  {
1967  /* Save the hardware error detected. This will be passed back to the API. */
1968  *pHwError = hDevice->nHwError;
1969 
1970  /* Clear any hardware errors detected. */
1971  hDevice->nHwError = 0u;
1972 
1974  }
1975  else
1976  {
1977  return(ADI_UART_SUCCESS);
1978  }
1979 }
2001  ADI_UART_HANDLE const hDevice,
2002  bool *const pbAvailable
2003  )
2004 {
2005 
2006 #ifdef ADI_DEBUG
2007  /* Validate the given handle. */
2008  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2009  {
2010  return(ADI_UART_INVALID_HANDLE);
2011  }
2012 
2013  /* This function is only allowed to be called when the channel is operating in NONBLOCKING mode. */
2014  if(hDevice->pChannelTx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
2015  {
2017  }
2018 #endif /* ADI_DEBUG */
2019 
2020  /* Initialize to "false" in case of an error. */
2021  *pbAvailable = false;
2022 
2023  /* Make sure the buffer has not already been processed. This would mean that there are
2024  currently no active buffers. This is only updated in adi_uart_GetBuffer(), which is
2025  called once a transaction has completed.
2026  */
2027  if (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)
2028  {
2029  /* If the buffer has reached the interrupt handler, "bInUse" will be
2030  updated so we know that the buffer has become available.
2031  */
2032  if (hDevice->pChannelTx->pActiveBuffer->bInUse == false)
2033  {
2034  *pbAvailable = true;
2035  }
2036  }
2037  return(ADI_UART_SUCCESS);
2038 }
2039 
2057  ADI_UART_HANDLE const hDevice,
2058  bool *const pbAvailable
2059  )
2060 {
2061 
2062 #ifdef ADI_DEBUG
2063  /* Validate the given handle. */
2064  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2065  {
2066  return(ADI_UART_INVALID_HANDLE);
2067  }
2068 
2069  /* This function is only allowed to be called when the channel is operating in NONBLOCKING mode. */
2070  if(hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_BLOCKING)
2071  {
2073  }
2074 #endif /* ADI_DEBUG */
2075 
2076  /* Initialize to "false" in case of an error. */
2077  *pbAvailable = false;
2078 
2079  /* Make sure the buffer has not already been processed. This would mean that there are
2080  currently no active buffers. This is only updated in adi_uart_GetBuffer(), which is
2081  called once a transaction has completed.
2082  */
2083  if(hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)
2084  {
2085  /* If the buffer has reached the interrupt handler, "bInUse" will be
2086  updated so we know that the buffer has become available.
2087  */
2088  if (hDevice->pChannelRx->pActiveBuffer->bInUse == false)
2089  {
2090  *pbAvailable = true;
2091  }
2092  }
2093  return(ADI_UART_SUCCESS);
2094 }
2095 
2116  ADI_UART_HANDLE const hDevice,
2117  bool *const pbComplete
2118  )
2119 {
2120 #ifdef ADI_DEBUG
2121  /* Validate the given handle. */
2122  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2123  {
2124  return(ADI_UART_INVALID_HANDLE);
2125  }
2126 #endif /* ADI_DEBUG */
2127 
2128  /* Initialize to false. */
2129  *pbComplete = false;
2130 
2131  /* If the register is empty, set the return variable to "true".
2132  This register is empty, when the value becomes a 1.
2133  */
2134  if((hDevice->pUARTRegs->LSR & BITM_UART_LSR_TEMT) == BITM_UART_LSR_TEMT)
2135  {
2136  *pbComplete = true;
2137  }
2138  return(ADI_UART_SUCCESS);
2139 }
2140 
2141 
2158  ADI_UART_HANDLE const hDevice,
2159  const ADI_CALLBACK pfCallback,
2160  void *const pCBParam
2161  )
2162 {
2163 
2164 #ifdef ADI_DEBUG
2165  /* Validate the given handle. */
2166  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2167  {
2168  return(ADI_UART_INVALID_HANDLE);
2169  }
2170 
2171  /* Make sure there are no active buffers on any active channel and autobaud is not in progress. */
2172  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
2173  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)) ||
2174  (hDevice->bAutobaudInProgress == true))
2175  {
2176  return(ADI_UART_DEVICE_IN_USE);
2177  }
2178 #endif /* ADI_DEBUG */
2179 
2180  /* Set the device callback. */
2181  hDevice->pfCallback = pfCallback;
2182 
2183  /* Set the callback parameter. */
2184  hDevice->pCBParam = pCBParam;
2185 
2186  return(ADI_UART_SUCCESS);
2187 }
2188 
2189 
2209  ADI_UART_HANDLE const hDevice,
2210  ADI_UART_PARITY const eParity,
2211  ADI_UART_STOPBITS const eStopBits,
2212  ADI_UART_WORDLEN const eWordLength
2213  )
2214 {
2215 #ifdef ADI_DEBUG
2216  /* Validate the given handle. */
2217  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2218  {
2219  return(ADI_UART_INVALID_HANDLE);
2220  }
2221 
2222  /* Make sure there are no active buffers on any active channel and autobaud is not in progress. */
2223  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
2224  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)) ||
2225  (hDevice->bAutobaudInProgress == true))
2226  {
2227  return(ADI_UART_DEVICE_IN_USE);
2228  }
2229 #endif /* ADI_DEBUG */
2230 
2231  /* Clear all the fields. */
2232  uint16_t nDataCfg = hDevice->pUARTRegs->LCR & (uint16_t)(~(BITM_UART_LCR_WLS |BITM_UART_LCR_STOP |BITM_UART_LCR_PEN));
2233 
2234  /* Construct the configuration word. */
2235  nDataCfg |= (uint16_t)(((uint16_t)((uint16_t)eWordLength |(uint16_t)eStopBits) |(uint16_t)eParity));
2236 
2237  /* Write to the register */
2238  hDevice->pUARTRegs->LCR = nDataCfg;
2239 
2240  /* Return Success */
2241  return(ADI_UART_SUCCESS);
2242 }
2243 
2271  ADI_UART_HANDLE const hDevice,
2272  uint16_t const nDivC,
2273  uint8_t const nDivM,
2274  uint16_t const nDivN,
2275  uint8_t const nOSR
2276  )
2277 {
2278 #ifdef ADI_DEBUG
2279  /* Validate the given handle */
2280  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2281  {
2282  return(ADI_UART_INVALID_HANDLE);
2283  }
2284 
2285  /* Make sure there are no active buffers on any active channel. */
2286  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
2287  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)))
2288  {
2289  return(ADI_UART_DEVICE_IN_USE);
2290  }
2291 
2292  /* Check if the given baudrate is valid */
2293  if( (nDivM < 1u) || (nDivM > 3u)|| (nDivN > 2047u ) || (nOSR > 3u))
2294  {
2296  }
2297 
2298 #endif /* ADI_DEBUG */
2299 
2300  /* Write back the register contents for baudrate detection in the hardware. */
2301  hDevice->pUARTRegs->DIV = nDivC;
2302  hDevice->pUARTRegs->FBR = (uint16_t)((uint16_t)nDivN | (uint16_t)((uint16_t)nDivM <<BITP_UART_FBR_DIVM)) | (uint16_t)BITM_UART_FBR_FBEN;
2303  hDevice->pUARTRegs->LCR2 = nOSR;
2304 
2305  return(ADI_UART_SUCCESS);
2306 }
2307 
2308 
2336 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
2338  ADI_UART_HANDLE const hDevice,
2339  ADI_DMA_MODE const eMode)
2340 {
2341 #ifdef ADI_DEBUG
2342  /* Validate the given handle */
2343  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2344  {
2345  return(ADI_UART_INVALID_HANDLE);
2346  }
2347 
2348  if(ValidateDmaMode(hDevice, eMode) != ADI_UART_SUCCESS)
2349  {
2351  }
2352 
2353 #endif /* ADI_DEBUG */
2354 
2355  /* Clear the cycle control bits */
2356 
2357  /* Set the DMA Mode */
2358 
2359  switch (eMode)
2360  {
2361  case ADI_DMA_MODE_BASIC:
2362  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
2363  break;
2364 
2366  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PING_PONG;
2367  break;
2368 
2369  case ADI_DMA_MODE_PSG:
2370  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI;
2371  break;
2372 
2373  default:
2374  hDevice->pChannelTx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
2375  break;
2376  }
2377 
2378  return(ADI_UART_SUCCESS);
2379 }
2380 #endif
2381 
2382 
2410 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
2412  ADI_UART_HANDLE const hDevice,
2413  ADI_DMA_MODE const eMode)
2414 {
2415 #ifdef ADI_DEBUG
2416  /* Validate the given handle */
2417  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2418  {
2419  return(ADI_UART_INVALID_HANDLE);
2420  }
2421 
2422  if(ValidateDmaMode(hDevice, eMode) != ADI_UART_SUCCESS)
2423  {
2425  }
2426 
2427 #endif /* ADI_DEBUG */
2428 
2429  /* Clear the cycle control bits */
2430 
2431  /* Set the DMA Mode */
2432 
2433  switch (eMode)
2434  {
2435  case ADI_DMA_MODE_BASIC:
2436  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
2437  break;
2438 
2440  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PING_PONG;
2441  break;
2442 
2443  case ADI_DMA_MODE_PSG:
2444  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_PSG_PRI;
2445  break;
2446 
2447  default:
2448  hDevice->pChannelRx->pFreeBuffer->nDmaMode = DMA_ENUM_CTL_CYCLE_CTL_BASIC;
2449  break;
2450  }
2451 
2452  return(ADI_UART_SUCCESS);
2453 }
2454 #endif
2455 
2456 
2477  ADI_UART_HANDLE const hDevice,
2478  uint32_t *pnBaudRate,
2479  uint32_t *pAutobaudError
2480  )
2481 {
2482 
2483 #ifdef ADI_DEBUG
2484  /* Validate the given handle. */
2485  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2486  {
2487  return(ADI_UART_INVALID_HANDLE);
2488  }
2489 
2490  /* Validate pointers. */
2491  if(pnBaudRate == NULL)
2492  {
2493  return(ADI_UART_INVALID_POINTER);
2494  }
2495 
2496 #endif /* ADI_DEBUG */
2497 
2498  /* If an error occured during autobaud this value will be set to a
2499  non-zero value. The specific error can be found by checking against
2500  #ADI_UART_EVENT.
2501  */
2502  if(hDevice->nAutobaudError != 0u)
2503  {
2504  /* Save the autobaud error to pass back to the API.*/
2505  *pAutobaudError = hDevice->nAutobaudError;
2506 
2507  /* Clear the autobaud errors found. */
2508  hDevice->nAutobaudError = 0u;
2509 
2511  }
2512 
2513  /* Return the baudrate. If this is 0, then autobaud has not completed. */
2514  *pnBaudRate = hDevice->nBaudRate;
2515 
2516  return(ADI_UART_SUCCESS);
2517 }
2518 
2519 
2546  ADI_UART_HANDLE const hDevice,
2547  bool const bEnable,
2548  bool const bAutobaudCallbackMode
2549  )
2550 {
2551 
2552 #ifdef ADI_DEBUG
2553  /* Validate the given handle */
2554  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2555  {
2556  return(ADI_UART_INVALID_HANDLE);
2557  }
2558 
2559  /* Make sure there are no active buffers on any active channel and autobaud is not in progress. */
2560  if(((hDevice->eDirection != ADI_UART_DIR_TRANSMIT) && (hDevice->pChannelRx->pActiveBuffer->pStartAddress != NULL)) ||
2561  ((hDevice->eDirection != ADI_UART_DIR_RECEIVE ) && (hDevice->pChannelTx->pActiveBuffer->pStartAddress != NULL)))
2562  {
2563  return(ADI_UART_DEVICE_IN_USE);
2564  }
2565 
2566 #endif /* ADI_DEBUG */
2567 
2568  if(bEnable)
2569  {
2570  /* Enable Autobaud, timeout interrupt and done interrupt in the autobaud control register.
2571  Set the starting edge trigger to the second edge. Set the ending edge count to
2572  the fourth edge, for the carrige return key character (0xD).
2573  */
2574  hDevice->pUARTRegs->ACR |=(BITM_UART_ACR_ABE | BITM_UART_ACR_DNIEN | BITM_UART_ACR_TOIEN |(1u << 4u) | (3u << 8u));
2575 
2576  /* Initialize device baudrate to 0. This will be set once autobaud is complete. */
2577  hDevice->nBaudRate = 0u;
2578 
2579  /* Change the state to indicate autobaud is in progress. */
2580  hDevice->bAutobaudInProgress = true;
2581 
2582  /* Set the callback mode for autobaud based on the user input. */
2583  hDevice->bAutobaudCallbackMode = bAutobaudCallbackMode;
2584  }
2585  else
2586  {
2587  /* Change the state to indicate autobaud is not in progress. */
2588  hDevice->bAutobaudInProgress = false;
2589 
2590  /* Disable Autobaud, timeout interrupt and done interrupt in the autobaud control register. */
2591  hDevice->pUARTRegs->ACR &= (uint16_t)~(BITM_UART_ACR_ABE |
2592  BITM_UART_ACR_DNIEN |
2593  BITM_UART_ACR_TOIEN );
2594 
2595  /* Initialize device baudrate to 0. */
2596  hDevice->nBaudRate = 0u;
2597  }
2598 
2599  return ADI_UART_SUCCESS;
2600 }
2601 
2620  ADI_UART_HANDLE const hDevice,
2621  bool const bEnable
2622  )
2623 {
2624 
2625 #ifdef ADI_DEBUG
2626  /* Validate the given handle. */
2627  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2628  {
2629  return(ADI_UART_INVALID_HANDLE);
2630  }
2631 #endif /* ADI_DEBUG */
2632 
2633  if(bEnable == true)
2634  {
2635  /* Set the force break bit. */
2636  hDevice->pUARTRegs->LCR |= BITM_UART_LCR_BRK;
2637  }
2638  else
2639  {
2640  /* Clear the force break bit. */
2641  hDevice->pUARTRegs->LCR &= (uint16_t)~(BITM_UART_LCR_BRK);
2642  }
2643 
2644  return ADI_UART_SUCCESS;
2645 }
2646 
2659  ADI_UART_HANDLE const hDevice,
2660  bool const bEnable
2661  )
2662 {
2663 
2664 #ifdef ADI_DEBUG
2665  /* Validate the given handle. */
2666  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2667  {
2668  return(ADI_UART_INVALID_HANDLE);
2669  }
2670 #endif /* ADI_DEBUG */
2671 
2672  if(true == bEnable)
2673  {
2674  /* Enable loopback. */
2675  hDevice->pUARTRegs->MCR |= (BITM_UART_MCR_LOOPBACK);
2676  }
2677  else
2678  {
2679  /* Disable loopback. */
2680  hDevice->pUARTRegs->MCR &= (uint16_t)~(BITM_UART_MCR_LOOPBACK);
2681  }
2682  return(ADI_UART_SUCCESS);
2683 }
2684 
2698  ADI_UART_HANDLE const hDevice,
2699  ADI_UART_TRIG_LEVEL const eTriglevel
2700  )
2701 {
2702 #ifdef ADI_DEBUG
2703  /* Validate the given handle. */
2704  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2705  {
2706  return(ADI_UART_INVALID_HANDLE);
2707  }
2708 #endif /* ADI_DEBUG */
2709 
2710  /* Clear existing FIFO trigger level. */
2711  hDevice->pUARTRegs->FCR &= (uint16_t)~BITM_UART_FCR_RFTRIG;
2712 
2713  /* Set the FIFO trigger level. */
2714  hDevice->pUARTRegs->FCR |= (uint16_t)eTriglevel;
2715 
2716  /* Update the internal structure */
2717  hDevice->nRxFifoTrig = sFifoTriggers[eTriglevel >> BITP_UART_FCR_RFTRIG];
2718 
2719  return(ADI_UART_SUCCESS);
2720 }
2733  ADI_UART_HANDLE const hDevice,
2734  bool const bEnable
2735  )
2736 {
2737 
2738 #ifdef ADI_DEBUG
2739  /* Validate the given handle. */
2740  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2741  {
2742  return(ADI_UART_INVALID_HANDLE);
2743  }
2744 #endif /* ADI_DEBUG */
2745 
2746  if(bEnable == true)
2747  {
2748  /* Enable TX/RX FIFO. */
2749  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_FIFOEN;
2750 
2751  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
2752  also doesn't modify the same register concurrently */
2753  ADI_INT_STATUS_ALLOC();
2754  ADI_ENTER_CRITICAL_REGION();
2755  hDevice->pUARTRegs->IEN |= (BITM_UART_IEN_ERBFI);
2756  ADI_EXIT_CRITICAL_REGION();
2757 
2758  hDevice->bRxFifoEn = true;
2759 
2760  }
2761  else
2762  {
2763  /* Disable TX/RX FIFO. */
2764  hDevice->pUARTRegs->FCR &= (uint16_t)~(BITM_UART_FCR_FIFOEN);
2765 
2766  hDevice->bRxFifoEn = false;
2767  }
2768 
2769  return ADI_UART_SUCCESS;
2770 }
2771 
2784  ADI_UART_CONST_HANDLE const hDevice
2785  )
2786 {
2787 
2788 #ifdef ADI_DEBUG
2789  /* Validate the given handle. */
2790  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2791  {
2792  return(ADI_UART_INVALID_HANDLE);
2793  }
2794 #endif /* ADI_DEBUG */
2795 
2796  /* Flush the Tx FIFO. */
2797  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_TFCLR;
2798 
2799  return(ADI_UART_SUCCESS);
2800 }
2801 
2814  ADI_UART_CONST_HANDLE const hDevice
2815  )
2816 {
2817 
2818 #ifdef ADI_DEBUG
2819  /* Validate the given handle. */
2820  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2821  {
2822  return(ADI_UART_INVALID_HANDLE);
2823  }
2824 #endif /* ADI_DEBUG */
2825 
2826  /* Flush RX FIFO. */
2827  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_RFCLR;
2828 
2829  return ADI_UART_SUCCESS;
2830 }
2831 
2846  ADI_UART_CONST_HANDLE const hDevice
2847  )
2848 {
2849 
2850 #ifdef ADI_DEBUG
2851  /* Validate the given handle. */
2852  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2853  {
2854  return(ADI_UART_INVALID_HANDLE);
2855  }
2856 #endif /* ADI_DEBUG */
2857 
2858  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
2859  also doesn't modify the same register concurrently */
2860  ADI_INT_STATUS_ALLOC();
2861  ADI_ENTER_CRITICAL_REGION();
2862  /* Disable receive interrupts in PIO mode as well as DMA mode. */
2863  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ERBFI | BITM_UART_IEN_EDMAR);
2864  ADI_EXIT_CRITICAL_REGION();
2865 
2866  /* Clear any data in the Rx Fifo. */
2867  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_RFCLR;
2868 
2869  /* Reset the data transfer mode. */
2870  hDevice->pChannelRx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
2871 
2872  /* Reset the buffers to 0. */
2873  memset(hDevice->pChannelRx->PingPong,0, sizeof (hDevice->pChannelRx->PingPong));
2874 
2875  hDevice->pChannelRx->PingPong[0].pNextBuffer = &hDevice->pChannelRx->PingPong[1];
2876  hDevice->pChannelRx->PingPong[1].pNextBuffer = &hDevice->pChannelRx->PingPong[0];
2877 
2878  /* Reset the buffer pointers. */
2879  hDevice->pChannelRx->pActiveBuffer = &hDevice->pChannelRx->PingPong[0];
2880  hDevice->pChannelRx->pFreeBuffer = &hDevice->pChannelRx->PingPong[0];
2881  hDevice->pChannelRx->pFillBuffer = &hDevice->pChannelRx->PingPong[0];
2882 
2883  /* Dummy read to flush the RX register. */
2884  hDevice->pUARTRegs->RX;
2885 
2886  return(ADI_UART_SUCCESS);
2887 }
2888 
2902 {
2903 
2904 #ifdef ADI_DEBUG
2905  /* Validate the given handle. */
2906  if(ValidateHandle(hDevice) != ADI_UART_SUCCESS)
2907  {
2908  return(ADI_UART_INVALID_HANDLE);
2909  }
2910 #endif /* ADI_DEBUG */
2911 
2912  /* Protecting IEN register writes by disabling interrupts ensures the interrupt handler
2913  also doesn't modify the same register concurrently */
2914  ADI_INT_STATUS_ALLOC();
2915  ADI_ENTER_CRITICAL_REGION();
2916  /* Disable transmit interrupts in PIO mode as well as DMA mode. */
2917  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ETBEI | BITM_UART_IEN_EDMAT);
2918  ADI_EXIT_CRITICAL_REGION();
2919 
2920  /* Clear any data in the Rx Fifo. */
2921  hDevice->pUARTRegs->FCR |= BITM_UART_FCR_TFCLR;
2922 
2923  /* Reset the data transfer mode. */
2924  hDevice->pChannelTx->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
2925 
2926  /* Reset the buffers to 0. */
2927  memset(hDevice->pChannelTx->PingPong,0, sizeof (hDevice->pChannelTx->PingPong));
2928 
2929  hDevice->pChannelTx->PingPong[0].pNextBuffer = &hDevice->pChannelTx->PingPong[1];
2930  hDevice->pChannelTx->PingPong[1].pNextBuffer = &hDevice->pChannelTx->PingPong[0];
2931 
2932  /* Reset the buffer pointers. */
2933  hDevice->pChannelTx->pActiveBuffer = &hDevice->pChannelTx->PingPong[0];
2934  hDevice->pChannelTx->pFreeBuffer = &hDevice->pChannelTx->PingPong[0];
2935  hDevice->pChannelTx->pFillBuffer = &hDevice->pChannelTx->PingPong[0];
2936 
2937  return(ADI_UART_SUCCESS);
2938 }
2939 
2942 void UART0_Int_Handler(void)
2943 {
2944  ISR_PROLOG();
2945  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)uart_device_info[0].hDevice;
2946  Common_Uart_Interrupt_Handler(hDevice);
2947 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2949 #endif
2950  ISR_EPILOG();
2951  return;
2952 }
2953 
2954 #if defined (__ADUCM4x50__)
2955 
2956 void UART1_Int_Handler(void)
2957 {
2958  ISR_PROLOG();
2959  ADI_UART_HANDLE hDevice = (ADI_UART_HANDLE)uart_device_info[1].hDevice;
2960  Common_Uart_Interrupt_Handler(hDevice);
2961 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
2963 #endif
2964  ISR_EPILOG();
2965  return;
2966 }
2967 #endif
2968 
2969 static void Common_Uart_Interrupt_Handler(ADI_UART_HANDLE hDevice)
2970 {
2971  switch(hDevice->pUARTRegs->IIR & BITM_UART_IIR_STAT )
2972  {
2973  /* Tx buffer empty interrupt. This means that the data has successfully left the holding register and is
2974  now in transmit shift register or has completed its transfer.
2975  */
2976  case ENUM_UART_IIR_STAT_ETBEI:
2977  uart_TxDataHandler(hDevice);
2978  break;
2979 
2980  /* Rx buffer FIFO timeout interrupt. This means that we have data in the RX FIFO
2981  but there is not enough data to trigger an interrupt so we will process this data here.
2982  */
2983  case ENUM_UART_IIR_STAT_RFTOI:
2984  /* Extract as many bytes in Rx FIFO as possible.
2985  * subsequent timeout int will take care of remaining bytes if needed. */
2986  uart_RxDataHandler(hDevice, hDevice->pUARTRegs->RFC);
2987  break;
2988 
2989  /* Rx buffer full interrupt. This means that the RX buffer has finished receiving data. */
2990  case ENUM_UART_IIR_STAT_ERBFI:
2991  /* Extract the amount of data based on the size of the trigger */
2992  uart_RxDataHandler(hDevice, hDevice->nRxFifoTrig);
2993  break;
2994 
2995  /* Line status interrupt. */
2996  case ENUM_UART_IIR_STAT_RLSI:
2997  {
2998  /* Initialze the line status event to 0. */
2999  uint32_t nEvent = 0u;
3000 
3001  /* Get the interrupts status. */
3002  uint16_t nStatus = hDevice->pUARTRegs->LSR;
3003 
3004  /* If a break signal is detected.. */
3005  if((BITM_UART_LSR_BI & nStatus) == BITM_UART_LSR_BI)
3006  {
3007  /* Dummy read to flush the RX register. We do this because
3008  we do not actaully want to do anything with this data as it
3009  is only a break indicator. */
3010  hDevice->pUARTRegs->RX;
3011 
3012  /* Set the event to a break interrupt. */
3013  nEvent = (uint32_t)ADI_UART_BREAK_INTERRUPT;
3014  }
3015 
3016  /* Ignore the framing error if the break is asserted.
3017  We do this because a break can trigger a false framing error.
3018  */
3019  else if((BITM_UART_LSR_FE & nStatus) == BITM_UART_LSR_FE)
3020  {
3021  /* Set the event to show a framing error has been detected. */
3022 #if !defined(ADI_UART_DRAIN_RX_BUFFER) || (0==ADI_UART_DRAIN_RX_BUFFER)
3023  nEvent |= (uint32_t)ADI_UART_HW_ERR_FRAMING;
3024 #endif
3025  }
3026  else
3027  {
3028  /* Do nothing. This is required for MISRA. */
3029  }
3030 
3031  if((BITM_UART_LSR_PE & nStatus) == BITM_UART_LSR_PE)
3032  {
3033  /* Set the event to show a parity error has been detected. */
3034  nEvent |= (uint32_t)ADI_UART_HW_ERR_PARITY;
3035  }
3036  if((BITM_UART_LSR_OE & nStatus) == BITM_UART_LSR_OE)
3037  {
3038  /* Set the event to show a hardware overrun error has been detected, meaning receive data has
3039  been overwritten.
3040  */
3041  nEvent |= (uint32_t)ADI_UART_HW_ERR_OVERRUN;
3042  }
3043 
3044  /* If there was an event and autobaud is not in progress, notify the API. */
3045  if((nEvent != 0u) && (hDevice->bAutobaudInProgress == false))
3046  {
3047  /* Set the UART device hw error bit field. This will allow us to return the
3048  specific failure to the application once we return from this ISR.
3049  */
3050  hDevice->nHwError |= nEvent;
3051  if (ADI_UART_DIR_TRANSMIT != hDevice->eDirection) {
3052  uart_ManageProcessedBuffer(hDevice, hDevice->pChannelRx, ADI_UART_EVENT_HW_ERROR_DETECTED);
3053  }
3054  }
3055  break;
3056  }
3057 
3058  /* If there was a modem status interrupt. For our purposes, we will only check if this is related to autobaud. */
3059  case ENUM_UART_IIR_STAT_EDSSI:
3060  {
3061 #if (ADI_UART_CFG_ENABLE_AUTOBAUD == 1)
3062  /* Initialize the autobaud event to 0. */
3063  uint32_t nEvent = 0u;
3064 
3065  /* Get the autobaud interrupt status but not the counter value. */
3066  uint16_t nStatus = hDevice->pUARTRegs->ASRL & 0xFu;
3067 
3068  /* Read the autobaud control register to see if autobaud was enabled. */
3069  uint16_t acr = (hDevice->pUARTRegs->ACR & BITM_UART_ACR_ABE);
3070 
3071  /* If there is an autobaud event and autobaud is enabled */
3072  if((nStatus != 0u) && (acr != 0u))
3073  {
3074  uint32_t nClock;
3075  uint32_t nCount;
3076 
3077  /*Get the clock frequency. */
3079  {
3080  nClock = 0u;
3081  }
3082 
3083  /* Get the autobaud counter bits 12-19. */
3084  nCount = (uint32_t)hDevice->pUARTRegs->ASRH << 12u;
3085 
3086  /* Get the autobaud counter bits 0-11. */
3087  nCount |= (uint32_t)hDevice->pUARTRegs->ASRL >> 4u;
3088 
3089  /* if the autobaud event was that the autobaud is done.. */
3090  if((nStatus & BITM_UART_ASRL_DONE) == BITM_UART_ASRL_DONE)
3091  {
3092  /* If the fractional baud generator is enabled, calculate the fractional portional of the baudrate.
3093  It seems that in order to get a correct baudrate reading, we need the fractional divider enabled.
3094  */
3095  if ((hDevice->pUARTRegs->FBR & 0x8000u) == 0x8000u)
3096  {
3097  uint8_t nOSR = 0u;
3098  uint32_t nDivN;
3099  uint32_t nDivNSubtractor = 2048u;
3100 
3101  /* DIVC is always 1, unless the oversample rate is 32. */
3102  uint16_t nDivC = 1u;
3103 
3104  /* If the oversample rate is 4.. */
3105  if(nCount < (8u << 3u))
3106  {
3107  nDivN = ((nCount << 9u) / 8u) - nDivNSubtractor;
3108  }
3109 
3110  /* If the oversample rate is 8.. */
3111  else if(nCount < (8u << 4u))
3112  {
3113  nDivN = ((nCount << 8u) / 8u) - nDivNSubtractor;
3114  nOSR = 1u;
3115  }
3116 
3117  /* If the oversample rate is 16.. */
3118  else if(nCount < (8u << 5u))
3119  {
3120  nDivN = ((nCount << 7u) / 8u) - nDivNSubtractor;
3121  nOSR = 2u;
3122  }
3123 
3124  /* If the oversample rate is 32.. */
3125  else
3126  {
3127  nDivC = (uint16_t) (nCount / 32u / 8u);
3128  nDivN = ((nCount << 6u) / (8u * nDivC)) - nDivNSubtractor;
3129  nOSR = 3u;
3130  }
3131 
3132  /* Write back the register contents for baudrate detection in the hardware. */
3133  adi_uart_ConfigBaudRate(hDevice, nDivC, 1u, (uint16_t)nDivN, nOSR);
3134 
3135  /* For more precise calculations we would use floating point math here. Integer precision will do for now.
3136  This avoids bringing in extra libraries for floating point math. */
3137 
3138  /* Baudrate = (UARTCLK / (nDivM + nDivN / 2048) * pow(2, nOSR + 2) * nDivC)
3139  nOSR = (1u << (nOSR + 2u)); Seperate this out of the equation for misra compliance
3140  hDevice->nBaudRate = ((float)nClock / (((float)1 + (float)nDivN / (float)2048) * (float)nOSR * (float)nDivC));
3141  */
3142 
3143  /* In order to avoid bringing in the extra floating point libraries, we will use the non fractional baudrate for the API. */
3144  hDevice->nBaudRate = ((nClock * 8u) / nCount);
3145  }
3146  else
3147  {
3148  /* No Fractional divider: Baudrate (bits/second) = (UARTCLK (cycles/second) * counted bits (bits)) / nCount (cycles)*/
3149  hDevice->nBaudRate = ((nClock * 8u) / nCount);
3150  }
3151 
3152  /* If there is a callback, notify the API that autobaud is complete.
3153  If there is not a callback, the baudrate will be set to a non zero value so the user can call "Get_BaudRate"
3154  to know that autobaud has completed.
3155  */
3156  if((hDevice->pfCallback != NULL) && (hDevice->bAutobaudCallbackMode == true))
3157  {
3158  hDevice->pfCallback(hDevice->pCBParam, ADI_UART_EVENT_AUTOBAUD_COMPLETE, (void*)hDevice->nBaudRate);
3159  }
3160  }
3161  else
3162  {
3163  if((nStatus & BITM_UART_ASRL_BRKTO) == BITM_UART_ASRL_BRKTO)
3164  {
3165  /* Autobaud timed out due to break error. */
3166  nEvent |= (uint32_t)ADI_UART_AUTOBAUD_TIMEOUT_LONGBREAK;
3167  }
3168  if((nStatus & BITM_UART_ASRL_NSETO) == BITM_UART_ASRL_NSETO)
3169  {
3170  /* Autobaud timed out due to no valid start edge found. */
3171  nEvent |= (uint32_t)ADI_UART_AUTOBAUD_TIMEOUT_NO_START_EDGE;
3172  }
3173  if((nStatus & BITM_UART_ASRL_NEETO) == BITM_UART_ASRL_NEETO)
3174  {
3175  /* Autobaud timed out due to no valid end edge found. */
3176  nEvent |= (uint32_t)ADI_UART_AUTOBAUD_TIMEOUT_NO_END_EDGE;
3177  }
3178  /* If there is an event callback.. */
3179  if((hDevice->pfCallback != NULL) && (hDevice->pChannelRx->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING))
3180  {
3181  /* Notify application of errors through callback. */
3182  hDevice->pfCallback(hDevice->pCBParam, ADI_UART_EVENT_AUTOBAUD_ERROR_DETECTED, (void*)nEvent);
3183  }
3184  else
3185  {
3186  /* Notify application of errors through autobaud return value. */
3187  hDevice->nAutobaudError = nEvent;
3188  }
3189 
3190  }
3191 
3192  /* Dummy read to flush the RX register to clear the key character that was sent while configuring autobaud. */
3193  hDevice->pUARTRegs->RX;
3194  }
3195 #endif
3196  /* Clear auto baud enable and interrupt registers. We disable autobaud here because it is required in order to clear the counter. */
3197  hDevice->pUARTRegs->ACR &=(uint16_t)~( BITM_UART_ACR_ABE |
3198  BITM_UART_ACR_DNIEN |
3199  BITM_UART_ACR_TOIEN );
3200 
3201  hDevice->bAutobaudInProgress = false;
3202  break;
3203  }
3204  default:
3205  break;
3206  }
3207  return;
3208 }
3209 
3210 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
3211 static void Common_DMA_Uart_Interrupt_Handler(ADI_UART_HANDLE hDevice, ADI_UART_DATA_CHANNEL* pChannel, ADI_UART_EVENT eEvent)
3212 {
3213  /* Increment the number of available descriptor */
3214  pChannel->nFreeDescriptor++;
3215 
3216  if(pChannel->pFillBuffer->nRemDoneTransfers > DMA_TRANSFER_LIMIT)
3217  {
3218  pChannel->pFillBuffer->nRemDoneTransfers -= DMA_TRANSFER_LIMIT;
3219  }
3220  else
3221  {
3222  pChannel->pFillBuffer->nRemDoneTransfers = 0;
3223  }
3224 
3225  /* If there are remaining bytes to be processed */
3226  if(pChannel->pFillBuffer->nCount > 0)
3227  {
3228  /* Set-up the DMA for the Tx Channel */
3229  pChannel->pfSubmitBuffer(hDevice, pChannel->pFillBuffer);
3230  }
3231 
3232  /* If all transactions are acknowledged */
3233  if(pChannel->pFillBuffer->nRemDoneTransfers ==0)
3234  {
3235  /* Manage the buffer */
3236  uart_ManageProcessedBuffer(hDevice, pChannel, eEvent);
3237  }
3238 }
3239 #endif
3240 
3241 
3242 /* DMA interrupt handlers */
3243 void DMA_UART0_TX_Int_Handler(void)
3244 {
3245  ISR_PROLOG();
3246  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[0].hDevice;
3247 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
3248  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
3249 #else
3250  Common_DMA_Uart_Interrupt_Handler(hDevice, hDevice->pChannelTx, ADI_UART_EVENT_TX_BUFFER_PROCESSED);
3251 #endif
3252 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
3254 #endif
3255  ISR_EPILOG();
3256 }
3257 
3258 void DMA_UART0_RX_Int_Handler(void)
3259 {
3260  ISR_PROLOG();
3261  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[0].hDevice;
3262 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
3263  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
3264 #else
3265  Common_DMA_Uart_Interrupt_Handler(hDevice, hDevice->pChannelRx, ADI_UART_EVENT_RX_BUFFER_PROCESSED);
3266 #endif
3267 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
3269 #endif
3270  ISR_EPILOG();
3271 }
3272 
3273 #if defined(__ADUCM4x50__)
3274 
3275 void DMA_UART1_TX_Int_Handler(void)
3276 {
3277  ISR_PROLOG();
3278  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[1].hDevice;
3279 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
3280  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
3281 #else
3282  Common_DMA_Uart_Interrupt_Handler(hDevice, hDevice->pChannelTx, ADI_UART_EVENT_TX_BUFFER_PROCESSED);
3283 #endif
3284 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
3286 #endif
3287  ISR_EPILOG();
3288 }
3289 
3290 void DMA_UART1_RX_Int_Handler(void)
3291 {
3292  ISR_PROLOG();
3293  ADI_UART_HANDLE const hDevice = (ADI_UART_HANDLE)uart_device_info[1].hDevice;
3294 #if !defined(ADI_UART_DMA_EXTENSION_ENABLE) || (0 == ADI_UART_DMA_EXTENSION_ENABLE)
3295  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelRx,ADI_UART_EVENT_RX_BUFFER_PROCESSED);
3296 #else
3297  Common_DMA_Uart_Interrupt_Handler(hDevice, hDevice->pChannelRx, ADI_UART_EVENT_RX_BUFFER_PROCESSED);
3298 #endif
3299 #if defined(ADI_CYCLECOUNT_UART_ISR_ENABLED) && (ADI_CYCLECOUNT_UART_ISR_ENABLED == 1u)
3301 #endif
3302  ISR_EPILOG();
3303 }
3304 #endif/*__ADUCM4x50__*/
3305 /*
3306  * @brief UART interrupt handler for receiving the data in interrupt mode.
3307  *
3308  * @param [in] hDevice Device handle obtained from adi_uart_Open().
3309  * @param [in] nBytes Number of bytes to read from the RX.
3310  *
3311 */
3312 static void uart_RxDataHandler(ADI_UART_HANDLE hDevice, uint8_t nBytes)
3313 {
3314  ADI_UART_BUFF_INFO *pFillBuffer = hDevice->pChannelRx->pFillBuffer;
3315 
3316  /* Address of the buffer to be filled. */
3317  volatile uint8_t *pNextData = (uint8_t *)pFillBuffer->pStartAddress;
3318 
3319  bool activeBufferAvailable = ( (pNextData != NULL)
3320  && (pFillBuffer->bInUse == true)
3321  );
3322  /* If there is an active buffer when we enter this handler. */
3323  if(activeBufferAvailable)
3324  {
3325 
3326 #if !defined(ADI_UART_DRAIN_RX_BUFFER) || (0==ADI_UART_DRAIN_RX_BUFFER)
3327 
3328  /* Extract the required amount of data from the FIFO/Rx
3329  * Buffer must not be overwritten
3330  */
3331  while ( (nBytes-- > 0)
3332  && (pFillBuffer->nIndex < pFillBuffer->nCount)
3333  )
3334  {
3335  /* Read data from the RX holding register into the buffer
3336  * at the indexed location.
3337  */
3338  pNextData[pFillBuffer->nIndex] = (uint8_t) hDevice->pUARTRegs->RX;
3339 
3340  /* Increment the buffer index to store the next data. */
3341  pFillBuffer->nIndex++;
3342  }
3343 
3344  /* If all of the data has been processed, manage the processed data
3345  * buffer. Otherwise we will leave everything as is and continue to
3346  * receive interrupts for the incoming data, until this buffer has
3347  * been filled.
3348  */
3349  if(pFillBuffer->nIndex == pFillBuffer->nCount)
3350  {
3351  uart_ManageProcessedBuffer( hDevice, hDevice->pChannelRx
3353  }
3354 
3355 #else
3356 
3357  /* There are two main criteria for this loop:
3358  *
3359  * - there are data in the Rx FIFO
3360  * - a valid buffer is available to store the data in Rx FIFO
3361  *
3362  * We keep the number of data in the Rx FIFO up to date
3363  */
3364  while (activeBufferAvailable)
3365  {
3366  /* Get the current number of bytes available in the UART Rx FIFO */
3367  nBytes = hDevice->pUARTRegs->RFC;
3368 
3369  /* if there are no bytes left then we can leave */
3370  if (!nBytes)
3371  {
3372  /* If there are bytes in the current pFillBuffer,
3373  * then return the buffer to the application.
3374  */
3375  if (pFillBuffer->nIndex)
3376  {
3377  uart_ManageProcessedBuffer(hDevice,
3378  hDevice->pChannelRx,
3380  }
3381  break;
3382  }
3383 
3384  while (nBytes--)
3385  {
3386  /* Read data from the RX holding register into the buffer
3387  * at the indexed location.
3388  */
3389  pNextData[pFillBuffer->nIndex] = hDevice->pUARTRegs->RX;
3390 
3391  /* Increment the buffer index to store the next data. */
3392  pFillBuffer->nIndex++;
3393 
3394  /* If the buffer is full. */
3395  if (pFillBuffer->nIndex == pFillBuffer->nCount)
3396  {
3397  /* Try to get a new buffer */
3398  uart_ManageProcessedBuffer(hDevice,
3399  hDevice->pChannelRx,
3401 
3402  /* Pick up the newly submitted buffer */
3403  pFillBuffer = hDevice->pChannelRx->pFillBuffer;
3404  pNextData = (uint8_t *)pFillBuffer->pStartAddress;
3405 
3406  /* Make sure it's an active buffer */
3407  activeBufferAvailable = ( (pNextData != NULL)
3408  && (pFillBuffer->bInUse == true)
3409  );
3410  /* if no active buffer is available then stop looping */
3411  if (!activeBufferAvailable)
3412  {
3413  break;
3414  }
3415  }
3416  }
3417  }
3418 
3419 #endif
3420  }
3421  /* If we do not have a buffer submitted.. */
3422  else
3423  {
3424  /* Ask the API for a buffer so we can process this data before having
3425  an overflow. if there is no callback, the API will not be able to
3426  submit a buffer in time.
3427  */
3428  if (hDevice->pfCallback != NULL)
3429  {
3430  hDevice->pfCallback( hDevice->pCBParam
3432  , NULL);
3433  }
3434 
3435  /* This check here is in case in the callback the application
3436  submitted a buffer. If they did not then we need to clear
3437  the RX register in order to clear this interrupt.
3438  */
3439  if( (pFillBuffer->pStartAddress == NULL)
3440  && (pFillBuffer->bInUse == false)
3441  )
3442  {
3443  hDevice->pUARTRegs->RX;
3444  }
3445  }
3446 
3447  return;
3448 }
3449 
3450 /*
3451  * @brief UART interrupt handler transmitting the data in interrupt mode.
3452  *
3453  * @param [in] hDevice Device handle obtained from adi_uart_Open().
3454  *
3455 */
3456 static void uart_TxDataHandler(ADI_UART_HANDLE hDevice)
3457 {
3458  volatile uint8_t *pNextData;
3459 
3460  /* If there is an active buffer.. */
3461  if((hDevice->pChannelTx->pFillBuffer->pStartAddress != NULL) && (hDevice->pChannelTx->pFillBuffer->bInUse == true))
3462  {
3463  /* Get the start address of the buffer we are transmitting data from. */
3464  pNextData = (uint8_t *)hDevice->pChannelTx->pFillBuffer->pStartAddress;
3465 
3466  /* Write data to the TX holding register. This will be shifted out at the baud rate by the shift register. */
3467  hDevice->pUARTRegs->TX = (uint16_t)pNextData[hDevice->pChannelTx->pFillBuffer->nIndex];
3468 
3469  /* Increment the buffer index. */
3470  hDevice->pChannelTx->pFillBuffer->nIndex++;
3471 
3472 
3473  /* If all of the characters have been transmitted, manage the data buffer. Otherwise we will leave everything
3474  as is and continue to transmit this data until everything is out of the buffer. */
3475  if(hDevice->pChannelTx->pFillBuffer->nIndex >= hDevice->pChannelTx->pFillBuffer->nCount)
3476  {
3477  uart_ManageProcessedBuffer(hDevice,hDevice->pChannelTx,ADI_UART_EVENT_TX_BUFFER_PROCESSED);
3478  }
3479  }
3480  return;
3481 }
3482 
3483 
3484 /*
3485  * @brief Function for managing the processed buffer. This gets called after the receive buffer has been filled
3486  * and when the transmit buffer has been emptied.
3487  *
3488  * @param [in] hDevice Device handle obtained from adi_uart_Open().
3489  * @param [in] pChannel Channel handler for the Tx or Rx.
3490  * @param [in] eEvent Indicate the event ID to be passed to registered callback function, if one has been registered.
3491  *
3492 */
3493 
3494 
3495 static void uart_ManageProcessedBuffer(ADI_UART_HANDLE hDevice,ADI_UART_DATA_CHANNEL *pChannel, ADI_UART_EVENT eEvent)
3496 {
3502  if (pChannel->eDataTranferMode != ADI_UART_DATA_TRANSFER_MODE_NONE)
3503  {
3504  pChannel->pFillBuffer->bInUse = false;
3505  pChannel->pFillBuffer = pChannel->pFillBuffer->pNextBuffer;
3506  }
3507 
3514  bool startNextTransaction = pChannel->pFillBuffer->bInUse;
3515 
3521  ADI_INT_STATUS_ALLOC();
3522  ADI_ENTER_CRITICAL_REGION();
3523  {
3525  {
3526  /* Disable Tx buffer interrupts. */
3527  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ETBEI | BITM_UART_IEN_EDMAT);
3528  }
3529  else
3530  {
3531  /* Disable Rx buffer interrupts for the DMA. We do not disable receive buffer full interrupts to allow
3532  the use of the RX FIFO.
3533  */
3534  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_EDMAR);
3535 
3536  if (hDevice->bRxFifoEn != true)
3537  {
3538  /* Disable Rx buffer interrupts for PIO mode if the FIFO is not enabled.
3539  */
3540  hDevice->pUARTRegs->IEN &= (uint16_t)~(BITM_UART_IEN_ERBFI);
3541  }
3542  }
3543  }
3544  ADI_EXIT_CRITICAL_REGION();
3545 
3555  if((hDevice->pfCallback != NULL) && (pChannel->eDataTranferMode == ADI_UART_DATA_TRANSFER_MODE_NONBLOCKING))
3556  {
3557  uint32_t nEvent = hDevice->nHwError;
3558  hDevice->nHwError = 0u;
3559 
3560  uint32_t *pBuffer = pChannel->pActiveBuffer->pStartAddress;
3561 
3562 #if !defined(ADI_UART_DRAIN_RX_BUFFER) || (0==ADI_UART_DRAIN_RX_BUFFER)
3563  void *pBuffArg = (void*) pBuffer;
3564 #else
3565  ADI_UART_RX_BUFFER_INFO rxBuffInfo = { (void*)pBuffer, pChannel->pActiveBuffer->nCount, pChannel->pActiveBuffer->nIndex };
3566  void *pBuffArg = (void*) &rxBuffInfo;
3567 #endif
3568 
3569  /* Reinitialize the start address to NULL so this buffer can be used for a new transaction. */
3570  pChannel->pActiveBuffer->pStartAddress = NULL;
3571 
3572  /* Now that the desired data has either been transmitted or received, this buffer is no longer
3573  in use. We can update "pActiveBuffer" to point to the next buffer that will become or is already
3574  active.
3575  */
3576  pChannel->pActiveBuffer = pChannel->pActiveBuffer->pNextBuffer;
3577 
3578  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
3579  This will only be done if there are no other active buffers in flight to avoid disrupting an active transfer.
3580  */
3581 
3582  if(pChannel->pActiveBuffer->pStartAddress == NULL)
3583  {
3584  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
3585  }
3586 
3587  if(nEvent != 0u)
3588  {
3589  hDevice->pfCallback(hDevice->pCBParam, ADI_UART_EVENT_HW_ERROR_DETECTED,(void*)nEvent);
3590  }
3591  else
3592  {
3593  hDevice->pfCallback(hDevice->pCBParam, (uint32_t)eEvent, pBuffArg);
3594  }
3595  /* Post to the blocking function. If we are in blocking mode, this will allow the buffer to be returned to the API.
3596  If we are in nonblocking mode, this will allow adi_uart_GetBuffer() to return immediately so the API can have
3597  control over the buffer again.
3598  */
3599  SEM_POST(pChannel);
3600  }
3601 
3602  else
3603  {
3604  /* Wait until the last bit is gone before POSTing the SEMAPHORE */
3606  while( ((hDevice->pUARTRegs->LSR & BITM_UART_LSR_TEMT) != BITM_UART_LSR_TEMT) ||(hDevice->pUARTRegs->TFC != 0u))
3607  {
3608  /*waiting until TFC becomes zero */
3609  }
3610  /* Set the data transfer mode to none so that the next transfer can be either in blocking or in nonblocking mode.
3611  This will only be done if there are no other active buffers in flight to avoid disrupting an active transfer.
3612  */
3613 
3614  if( pChannel->pActiveBuffer->pNextBuffer->pStartAddress==NULL)
3615  {
3616  pChannel->eDataTranferMode = ADI_UART_DATA_TRANSFER_MODE_NONE;
3617  }
3618 
3619  /* Post to the blocking function. If we are in blocking mode, this will allow the buffer to be returned to the API.
3620  If we are in nonblocking mode, this will allow adi_uart_GetBuffer() to return immediately so the API can have
3621  control over the buffer again.
3622  */
3623  SEM_POST(pChannel);
3624  }
3625 
3626  /* If there is another buffer active. The buffer we want to check is "pFillBuffer" because that is the next one that would
3627  be processed. So if it has been submitted, now would be the time to set up the interrupts based on its requirements.
3628  */
3629  if(startNextTransaction)
3630  {
3631  pChannel->pfSubmitBuffer(hDevice, pChannel->pFillBuffer);
3632  }
3633 }
3634 
3635 
3636 
3637 /*
3638  * @brief Initialize the UART instance to the default values specified in "adi_uart_config.h".
3639  *
3640  * @param [in] hDevice Device handle obtained from adi_uart_Open().
3641  * @param [in] nDeviceNum UART device number
3642 */
3643 
3644 static void uart_init(ADI_UART_CONST_HANDLE const hDevice, uint32_t const nDeviceNum)
3645 {
3646 
3647  ADI_UART_CONFIG const* pUARTCfg = &gUARTCfg[nDeviceNum];
3648 
3649  /* Line Control Register. */
3650  hDevice->pUARTRegs->LCR = pUARTCfg->LCR;
3651 
3652  /* Div-C in Baudrate divider register. */
3653  hDevice->pUARTRegs->DIV = pUARTCfg->DIV;
3654 
3655  /* Div-M and Div-N in Fractional Baudrate register. */
3656  hDevice->pUARTRegs->FBR = pUARTCfg->FBR;
3657 
3658  /* Second line control register. */
3659  hDevice->pUARTRegs->LCR2 = pUARTCfg->LCR2;
3660 
3661  /* FIFO control register. */
3662  hDevice->pUARTRegs->FCR = pUARTCfg->FCR;
3663 
3664  /* Half Duplex Control Register. */
3665  hDevice->pUARTRegs->RSC = pUARTCfg->RSC;
3666 
3667  /* Interrupt enable register. */
3668  hDevice->pUARTRegs->IEN = pUARTCfg->IEN;
3669 }
3670 
3671 #ifdef ADI_DEBUG
3672 /*
3673  * @brief Validate the device handle.
3674  *
3675  * @param [in] hDevice Device handle obtained from adi_uart_Open().
3676  *
3677  * @return Status
3678  * - #ADI_UART_SUCCESS Specified handle is valid.
3679  * - #ADI_UART_INVALID_HANDLE Specified handle is invalid.
3680  *
3681 */
3682 
3683 static ADI_UART_RESULT ValidateHandle(ADI_UART_CONST_HANDLE hDevice)
3684 {
3685  uint32_t i;
3686 
3687 
3688  for(i = 0U; i < ADI_UART_NUM_DEVICES; i++)
3689  {
3690 
3691  if((hDevice == uart_device_info[i].hDevice) && (hDevice != NULL))
3692  {
3693  return(ADI_UART_SUCCESS);
3694  }
3695  }
3696  return(ADI_UART_INVALID_HANDLE);
3697 }
3698 
3699  /*
3700  * @brief Validate the input parameters of the DMA mode.
3701  *
3702  *
3703  * @param [in] hDevice Device handle obtained from adi_uart_Open().
3704  * @param [in] eMode DMA mode/cycle control
3705  * @param [in] nBufSize Size of the buffer(in bytes).
3706  *
3707  * @return Status
3708  * - #ADI_UART_SUCCESS Specified parameters are valid.
3709  * - #ADI_UART_INVALID_PARAMETER Specified parameters are invalid.
3710  *
3711  */
3712 #if defined(ADI_UART_DMA_EXTENSION_ENABLE) && (ADI_UART_DMA_EXTENSION_ENABLE == 1)
3713 static ADI_UART_RESULT ValidateDmaMode(ADI_UART_CONST_HANDLE hDevice,
3714  uint8_t eMode)
3715 {
3716  ADI_UART_RESULT nResult;
3717 
3718  switch (eMode)
3719  {
3720  case ADI_DMA_MODE_INVALID:
3721  nResult = ADI_UART_SUCCESS;
3722  break;
3723 
3724  case ADI_DMA_MODE_BASIC:
3725  nResult = ADI_UART_SUCCESS;
3726  break;
3727 
3729  nResult = ADI_UART_SUCCESS;
3730  break;
3731 
3732  case ADI_DMA_MODE_PSG:
3733  nResult = ADI_UART_SUCCESS;
3734  break;
3735 
3736  default:
3737  nResult = ADI_UART_INVALID_PARAMETER;
3738  break;
3739  }
3740 
3741  return nResult;
3742 }
3743 #endif
3744 
3745 #endif /* ADI_DEBUG */
3746 
#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:232
ADI_UART_RESULT
Definition: adi_uart.h:107
ADI_UART_RESULT adi_uart_SetTxDmaMode(ADI_UART_HANDLE const hDevice, ADI_DMA_MODE const eMode)
Set the DMA Mode of the UART Tx Channel.
Definition: adi_uart.c:2337
#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:475
#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:2208
#define ADI_UART0_CFG_TRIG_LEVEL
__IO uint32_t DMASRCEND
Definition: adi_dma.h:176
ADI_UART_TRIG_LEVEL
Definition: adi_uart.h:205
#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:2056
#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:173
#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:2697
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:1352
#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:2783
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....
Definition: adi_uart.c:562
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:2157
#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:2845
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:2901
ADI_UART_DIRECTION
Definition: adi_uart.h:67
ADI_UART_RESULT adi_uart_SetRxDmaMode(ADI_UART_HANDLE const hDevice, ADI_DMA_MODE const eMode)
Set the DMA Mode of the UART Rx Channel.
Definition: adi_uart.c:2411
#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:2732
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:1294
#define ADI_UART0_CFG_ENABLE_MODEM_STATUS_INTERRUPT
ADI_UART_WORDLEN
Definition: adi_uart.h:223
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....
Definition: adi_uart.c:923
#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....
Definition: adi_uart.c:1490
#define ADI_UART0_CFG_HOLD_TX
ADI_DMA_MODE
Definition: adi_dma.h:100
#define ADI_UART_BIDIR_MEMORY_SIZE
Definition: adi_uart.h:50
ADI_UART_RESULT adi_uart_FlushRxFifo(ADI_UART_CONST_HANDLE const hDevice)
Flush the RX FIFO.
Definition: adi_uart.c:2813
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:2619
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:435
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:1690
ADI_UART_PARITY
Definition: adi_uart.h:240
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:2658
#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:2000
#define ADI_UART1_CFG_DIVN
ADI_UART_EVENT
Definition: adi_uart.h:83
#define ADI_UART1_CFG_TRIG_LEVEL
struct _ADI_UART_DEVICE * ADI_UART_HANDLE
Definition: adi_uart.h:55
#define ADI_CYCLECOUNT_ISR_DMA_UART_TX
__IO uint32_t DMADSTEND
Definition: adi_dma.h:177
ADI_UART_STOPBITS
Definition: adi_uart.h:259
#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:284
#define ADI_UART1_CFG_HOLD_TX
#define ADI_UART0_CFG_DIVM
ADI_UART_RESULT adi_uart_GetRX(ADI_UART_HANDLE const hDevice, uint8_t *const pRX)
Read the UART receive buffer register regardless of an error. This mode of reading a byte is done wit...
Definition: adi_uart.c:1878
#define ADI_UART1_CFG_WORD_LENGTH
#define ADI_UART_DMA_EXTENSION_ENABLE
__IO uint32_t DMACDC
Definition: adi_dma.h:178
const struct _ADI_UART_DEVICE * ADI_UART_CONST_HANDLE
Definition: adi_uart.h:60
void adi_dma_Init(void)
Initialize the DMA peripheral.
Definition: adi_dma.c:155
#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:2115
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:2270
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:2545
#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:2476
#define ADI_UART_UNIDIR_MEMORY_SIZE
Definition: adi_uart.h:45
#define ADI_UART0_CFG_ENABLE_PARITY
#define ADI_UART1_CFG_ENABLE_MODEM_STATUS_INTERRUPT