S32 SDK
lpuart_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
80 #include <stddef.h>
81 #include <stdbool.h>
82 #include "lpuart_hw_access.h"
83 #include "lpuart_irq.h"
84 #include "clock_manager.h"
85 
86 /*******************************************************************************
87  * Variables
88  ******************************************************************************/
89 
90 /* Pointer to lpuart runtime state structure */
92 
93 /* Table of base addresses for lpuart instances. */
95 
96 /* Table to save LPUART enum numbers defined in CMSIS files. */
98 
99 /* Table to save LPUART clock names as defined in clock manager. */
101 
102 /*******************************************************************************
103  * Private Functions
104  ******************************************************************************/
105 static status_t LPUART_DRV_StartSendDataUsingInt(uint32_t instance,
106  const uint8_t * txBuff,
107  uint32_t txSize);
108 #if FEATURE_LPUART_HAS_DMA_ENABLE
109 static status_t LPUART_DRV_StartSendDataUsingDma(uint32_t instance,
110  const uint8_t * txBuff,
111  uint32_t txSize);
112 #endif
113 static void LPUART_DRV_CompleteSendDataUsingInt(uint32_t instance);
114 #if FEATURE_LPUART_HAS_DMA_ENABLE
115 static void LPUART_DRV_CompleteSendDataUsingDma(void * parameter, edma_chn_status_t status);
116 #endif
117 static status_t LPUART_DRV_StartReceiveDataUsingInt(uint32_t instance,
118  uint8_t * rxBuff,
119  uint32_t rxSize);
120 #if FEATURE_LPUART_HAS_DMA_ENABLE
121 static status_t LPUART_DRV_StartReceiveDataUsingDma(uint32_t instance,
122  uint8_t * rxBuff,
123  uint32_t rxSize);
124 #endif
125 static void LPUART_DRV_CompleteReceiveDataUsingInt(uint32_t instance);
126 #if FEATURE_LPUART_HAS_DMA_ENABLE
127 static void LPUART_DRV_CompleteReceiveDataUsingDma(void * parameter, edma_chn_status_t status);
128 #endif
129 static void LPUART_DRV_PutData(uint32_t instance);
130 static void LPUART_DRV_GetData(uint32_t instance);
131 
132 /*******************************************************************************
133  * Code
134  ******************************************************************************/
135 /*FUNCTION**********************************************************************
136  *
137  * Function Name : LPUART_DRV_Init
138  * Description : This function initializes a LPUART instance for operation.
139  * This function will initialize the run-time state structure to keep track of
140  * the on-going transfers, ungate the clock to the LPUART module, initialize the
141  * module to user defined settings and default settings, configure the IRQ state
142  * structure and enable the module-level interrupt to the core, and enable the
143  * LPUART module transmitter and receiver.
144  * The following is an example of how to set up the lpuart_state_t and the
145  * lpuart_user_config_t parameters and how to call the LPUART_DRV_Init function
146  * by passing in these parameters:
147  * lpuart_user_config_t lpuartConfig;
148  * lpuartConfig.baudRate = 9600;
149  * lpuartConfig.bitCountPerChar = LPUART_8_BITS_PER_CHAR;
150  * lpuartConfig.parityMode = LPUART_PARITY_DISABLED;
151  * lpuartConfig.stopBitCount = LPUART_ONE_STOP_BIT;
152  * lpuartConfig.transferType = LPUART_USING_INTERRUPTS;
153  * lpuart_state_t lpuartState;
154  * LPUART_DRV_Init(instance, &lpuartState, &lpuartConfig);
155  *
156  * Implements : LPUART_DRV_Init_Activity
157  *END**************************************************************************/
158 status_t LPUART_DRV_Init(uint32_t instance, lpuart_state_t * lpuartStatePtr,
159  const lpuart_user_config_t * lpuartUserConfig)
160 {
161  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
162  DEV_ASSERT(lpuartStatePtr != NULL);
163  DEV_ASSERT(lpuartUserConfig != NULL);
164 
165  status_t lpuartStatus;
166  status_t osStatusRxSem;
167  status_t osStatusTxSem;
168  LPUART_Type * base = s_lpuartBase[instance];
169  uint32_t idx;
170 
171  /* Check if current instance is already initialized. */
172  DEV_ASSERT(s_lpuartStatePtr[instance] == NULL);
173 
174 #if FEATURE_LPUART_HAS_DMA_ENABLE
175  /* In DMA mode, only 8-bits chars are supported */
176  DEV_ASSERT((lpuartUserConfig->transferType != LPUART_USING_DMA) ||
177  (lpuartUserConfig->bitCountPerChar == LPUART_8_BITS_PER_CHAR));
178 #endif
179 
180  /* Clear the state struct for this instance. */
181  uint8_t *clearStructPtr = (uint8_t *)lpuartStatePtr;
182  for (idx = 0; idx < sizeof(lpuart_state_t); idx++)
183  {
184  clearStructPtr[idx] = 0;
185  }
186 
187  /* Save runtime structure pointer.*/
188  s_lpuartStatePtr[instance] = lpuartStatePtr;
189 
190  /* Save the transfer information for runtime retrieval */
191  lpuartStatePtr->transferType = lpuartUserConfig->transferType;
192  lpuartStatePtr->bitCountPerChar = lpuartUserConfig->bitCountPerChar;
193 #if FEATURE_LPUART_HAS_DMA_ENABLE
194  lpuartStatePtr->rxDMAChannel = lpuartUserConfig->rxDMAChannel;
195  lpuartStatePtr->txDMAChannel = lpuartUserConfig->txDMAChannel;
196 #endif
197 
198  /* initialize the LPUART instance */
199  LPUART_Init(base);
200 
201  /* initialize the parameters of the LPUART config structure with desired data */
202  lpuartStatus = LPUART_DRV_SetBaudRate(instance, lpuartUserConfig->baudRate);
203  if (lpuartStatus != STATUS_SUCCESS)
204  {
205  return STATUS_ERROR;
206  }
207  LPUART_SetBitCountPerChar(base, lpuartUserConfig->bitCountPerChar);
208  LPUART_SetParityMode(base, lpuartUserConfig->parityMode);
209  LPUART_SetStopBitCount(base, lpuartUserConfig->stopBitCount);
210 
211  /* initialize last driver operation status */
212  lpuartStatePtr->transmitStatus = STATUS_SUCCESS;
213  lpuartStatePtr->receiveStatus = STATUS_SUCCESS;
214 
215  /* finally, enable the LPUART transmitter and receiver */
216  LPUART_SetTransmitterCmd(base, true);
217  LPUART_SetReceiverCmd(base, true);
218 
219  /* Create the synchronization objects */
220  osStatusRxSem = OSIF_SemaCreate(&lpuartStatePtr->rxComplete, 0);
221  osStatusTxSem = OSIF_SemaCreate(&lpuartStatePtr->txComplete, 0);
222  if ((osStatusRxSem == STATUS_ERROR) || (osStatusTxSem == STATUS_ERROR))
223  {
224  return STATUS_ERROR;
225  }
226 
227  /* Install LPUART irq handler */
228  INT_SYS_InstallHandler(s_lpuartRxTxIrqId[instance], g_lpuartIsr[instance], (isr_t*) 0);
229 
230  /* Enable LPUART interrupt. */
232 
233  return STATUS_SUCCESS;
234 }
235 
236 /*FUNCTION**********************************************************************
237  *
238  * Function Name : LPUART_DRV_Deinit
239  * Description : This function shuts down the UART by disabling interrupts and
240  * transmitter/receiver.
241  *
242  * Implements : LPUART_DRV_Deinit_Activity
243  *END**************************************************************************/
244 status_t LPUART_DRV_Deinit(uint32_t instance)
245 {
246  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
247 
248  clock_names_t instanceClkName = s_lpuartClkNames[instance];
249  uint32_t lpuartSourceClock;
250  LPUART_Type * base = s_lpuartBase[instance];
251  const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
252 
253  (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);
254 
255  /* Check if current instance is already de-initialized or is gated.*/
256  DEV_ASSERT(s_lpuartStatePtr[instance] != NULL);
257  DEV_ASSERT(lpuartSourceClock > 0U);
258 
259  /* Wait until the data is completely shifted out of shift register */
260  while (!LPUART_GetStatusFlag(base, LPUART_TX_COMPLETE)) {}
261 
262  /* Destroy the synchronization objects */
263  (void)OSIF_SemaDestroy(&lpuartState->rxComplete);
264  (void)OSIF_SemaDestroy(&lpuartState->txComplete);
265 
266  /* Disable LPUART interrupt. */
268 
269  /* Restore default handler. */
271 
272  /* disable tx and rx */
273  LPUART_SetTransmitterCmd(base, false);
274  LPUART_SetReceiverCmd(base, false);
275 
276  /* Clear our saved pointer to the state structure */
277  s_lpuartStatePtr[instance] = NULL;
278 
279  return STATUS_SUCCESS;
280 }
281 
282 /*FUNCTION**********************************************************************
283  *
284  * Function Name : LPUART_DRV_InstallRxCallback
285  * Description : Install receive data callback function.
286  *
287  * Implements : LPUART_DRV_InstallRxCallback_Activity
288  *END**************************************************************************/
290  uart_callback_t function,
291  void * callbackParam)
292 {
293  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
294 
295  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
296 
297  uart_callback_t currentCallback = lpuartState->rxCallback;
298  lpuartState->rxCallback = function;
299  lpuartState->rxCallbackParam = callbackParam;
300 
301  return currentCallback;
302 }
303 
304 /*FUNCTION**********************************************************************
305  *
306  * Function Name : LPUART_DRV_InstallTxCallback
307  * Description : Install transmit data callback function, pass in NULL pointer
308  * as callback will uninstall.
309  *
310  * Implements : LPUART_DRV_InstallTxCallback_Activity
311  *END**************************************************************************/
313  uart_callback_t function,
314  void * callbackParam)
315 {
316  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
317 
318  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
319 
320  uart_callback_t currentCallback = lpuartState->txCallback;
321  lpuartState->txCallback = function;
322  lpuartState->txCallbackParam = callbackParam;
323 
324  return currentCallback;
325 }
326 
327 /*FUNCTION**********************************************************************
328  *
329  * Function Name : LPUART_DRV_SendDataBlocking
330  * Description : This function sends data out through the LPUART module using
331  * blocking method. The function does not return until the transmit is complete.
332  *
333  * Implements : LPUART_DRV_SendDataBlocking_Activity
334  *END**************************************************************************/
336  const uint8_t * txBuff,
337  uint32_t txSize,
338  uint32_t timeout)
339 {
340  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
341  DEV_ASSERT(txBuff != NULL);
342 
343  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
344  status_t retVal = STATUS_SUCCESS;
345  status_t syncStatus;
346 
347  /* Indicates this is a blocking transaction. */
348  lpuartState->isTxBlocking = true;
349 
350  DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
351  (lpuartState->transferType == LPUART_USING_DMA));
352 
353  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
354  {
355  /* Start the transmission process using interrupts */
356  retVal = LPUART_DRV_StartSendDataUsingInt(instance, txBuff, txSize);
357  }
358 #if FEATURE_LPUART_HAS_DMA_ENABLE
359  else
360  {
361  /* Start the transmission process using DMA */
362  retVal = LPUART_DRV_StartSendDataUsingDma(instance, txBuff, txSize);
363  }
364 #endif
365 
366  if (retVal == STATUS_SUCCESS)
367  {
368  /* Wait until the transmit is complete. */
369  syncStatus = OSIF_SemaWait(&lpuartState->txComplete, timeout);
370 
371  /* Finish the transmission if timeout expired */
372  if (syncStatus == STATUS_TIMEOUT)
373  {
374  lpuartState->isTxBlocking = false;
375  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
376  {
378  }
379 #if FEATURE_LPUART_HAS_DMA_ENABLE
380  else
381  {
382  LPUART_DRV_CompleteSendDataUsingDma(((void *)instance), EDMA_CHN_NORMAL);
383  }
384 #endif
385 
386  lpuartState->transmitStatus = STATUS_TIMEOUT;
387  retVal = STATUS_TIMEOUT;
388  }
389  }
390 
391  return retVal;
392 }
393 
394 /*FUNCTION**********************************************************************
395  *
396  * Function Name : LPUART_DRV_SendDataPolling
397  * Description : Send out multiple bytes of data using polling method.
398  *
399  * Implements : LPUART_DRV_SendDataPolling_Activity
400  *END**************************************************************************/
401 void LPUART_DRV_SendDataPolling(uint32_t instance,
402  const uint8_t *txBuff,
403  uint32_t txSize)
404 {
405  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
406  DEV_ASSERT(txBuff != NULL);
407 
408  const LPUART_Type * base = s_lpuartBase[instance];
409  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
410 
411  while (txSize > 0U)
412  {
413  while (!LPUART_GetStatusFlag(base, LPUART_TX_DATA_REG_EMPTY))
414  {}
415 
416  lpuartState->txBuff = txBuff;
417  LPUART_DRV_PutData(instance);
418 
419  if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
420  {
421  ++txBuff;
422  --txSize;
423  }
424  else
425  {
426  ++txBuff;
427  ++txBuff;
428  txSize -= 2U;
429  }
430  }
431 }
432 
433 /*FUNCTION**********************************************************************
434  *
435  * Function Name : LPUART_DRV_SendData
436  * Description : This function sends data out through the LPUART module using
437  * non-blocking method. The function will return immediately after calling this
438  * function.
439  *
440  * Implements : LPUART_DRV_SendData_Activity
441  *END**************************************************************************/
442 status_t LPUART_DRV_SendData(uint32_t instance,
443  const uint8_t * txBuff,
444  uint32_t txSize)
445 {
446  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
447  DEV_ASSERT(txBuff != NULL);
448 
449  status_t retVal = STATUS_SUCCESS;
450  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
451 
452  /* Indicates this is a non-blocking transaction. */
453  lpuartState->isTxBlocking = false;
454 
455  DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
456  (lpuartState->transferType == LPUART_USING_DMA));
457 
458  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
459  {
460  /* Start the transmission process using interrupts */
461  retVal = LPUART_DRV_StartSendDataUsingInt(instance, txBuff, txSize);
462  }
463 #if FEATURE_LPUART_HAS_DMA_ENABLE
464  else
465  {
466  /* Start the transmission process using DMA */
467  retVal = LPUART_DRV_StartSendDataUsingDma(instance, txBuff, txSize);
468  }
469 #endif
470 
471  return retVal;
472 }
473 
474 /*FUNCTION**********************************************************************
475  *
476  * Function Name : LPUART_DRV_GetTransmitStatus
477  * Description : This function returns whether the previous LPUART transmit has
478  * finished. When performing non-blocking transmit, the user can call this
479  * function to ascertain the state of the current transmission:
480  * in progress (or busy) or complete (success). In addition, if the transmission
481  * is still in progress, the user can obtain the number of words that have been
482  * currently transferred.
483  *
484  * Implements : LPUART_DRV_GetTransmitStatus_Activity
485  *END**************************************************************************/
486 status_t LPUART_DRV_GetTransmitStatus(uint32_t instance, uint32_t * bytesRemaining)
487 {
488  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
489  DEV_ASSERT(bytesRemaining != NULL);
490 
491  const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
492 
493  if (lpuartState->isTxBusy)
494  {
495  /* Fill in the bytes not transferred yet. */
496  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
497  {
498  /* In interrupt-based communication, the remaining bytes are retrieved
499  * from the state structure
500  */
501  *bytesRemaining = lpuartState->txSize;;
502  }
503 #if FEATURE_LPUART_HAS_DMA_ENABLE
504  else
505  {
506  /* In DMA-based communication, the remaining bytes are retrieved
507  * from the current DMA major loop count
508  */
509  *bytesRemaining = EDMA_DRV_GetRemainingMajorIterationsCount(lpuartState->txDMAChannel);
510  }
511 #endif
512  }
513  else
514  {
515  *bytesRemaining = 0;
516  }
517 
518  return lpuartState->transmitStatus;
519 }
520 
521 /*FUNCTION**********************************************************************
522  *
523  * Function Name : LPUART_DRV_AbortSendingData
524  * Description : This function terminates an non-blocking LPUART transmission
525  * early. During a non-blocking LPUART transmission, the user has the option to
526  * terminate the transmission early if the transmission is still in progress.
527  *
528  * Implements : LPUART_DRV_AbortSendingData_Activity
529  *END**************************************************************************/
531 {
532  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
533 
534  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
535 
536  /* Check if a transfer is running. */
537  if (!lpuartState->isTxBusy)
538  {
539  return STATUS_SUCCESS;
540  }
541 
542  /* Stop the running transfer. */
543  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
544  {
545  lpuartState->transmitStatus = STATUS_UART_ABORTED;
547  }
548 #if FEATURE_LPUART_HAS_DMA_ENABLE
549  else
550  {
551  lpuartState->transmitStatus = STATUS_UART_ABORTED;
552  LPUART_DRV_CompleteSendDataUsingDma(((void *)instance), EDMA_CHN_NORMAL);
553  }
554 #endif
555 
556  return STATUS_SUCCESS;
557 }
558 
559 /*FUNCTION**********************************************************************
560  *
561  * Function Name : LPUART_DRV_ReceiveDataBlocking
562  * Description : This function receives data from LPUART module using blocking
563  * method, the function does not return until the receive is complete.
564  *
565  * Implements : LPUART_DRV_ReceiveDataBlocking_Activity
566  *END**************************************************************************/
568  uint8_t * rxBuff,
569  uint32_t rxSize,
570  uint32_t timeout)
571 {
572  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
573  DEV_ASSERT(rxBuff != NULL);
574 
575  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
576  status_t retVal = STATUS_SUCCESS;
577  status_t syncStatus;
578 
579  /* Indicates this is a blocking transaction. */
580  lpuartState->isRxBlocking = true;
581 
582  DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
583  (lpuartState->transferType == LPUART_USING_DMA));
584 
585  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
586  {
587  /* Start the reception process using interrupts */
588  retVal = LPUART_DRV_StartReceiveDataUsingInt(instance, rxBuff, rxSize);
589  }
590 #if FEATURE_LPUART_HAS_DMA_ENABLE
591  else
592  {
593  /* Start the reception process using DMA */
594  retVal = LPUART_DRV_StartReceiveDataUsingDma(instance, rxBuff, rxSize);
595  }
596 #endif
597 
598  if (retVal == STATUS_SUCCESS)
599  {
600  /* Wait until the receive is complete. */
601  syncStatus = OSIF_SemaWait(&lpuartState->rxComplete, timeout);
602 
603  /* Finish the reception if timeout expired */
604  if (syncStatus == STATUS_TIMEOUT)
605  {
606  lpuartState->isRxBlocking = false;
607  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
608  {
610  }
611 #if FEATURE_LPUART_HAS_DMA_ENABLE
612  else
613  {
614  LPUART_DRV_CompleteReceiveDataUsingDma(((void *)instance), EDMA_CHN_NORMAL);
615  }
616 #endif
617 
618  lpuartState->receiveStatus = STATUS_TIMEOUT;
619  retVal = STATUS_TIMEOUT;
620  }
621  }
622 
623  return retVal;
624 }
625 
626 /*FUNCTION**********************************************************************
627  *
628  * Function Name : LPUART_DRV_ReceiveDataPolling
629  * Description : Receive multiple bytes of data using polling method.
630  *
631  * Implements : LPUART_DRV_ReceiveDataPolling_Activity
632  *END**************************************************************************/
634  uint8_t *rxBuff,
635  uint32_t rxSize)
636 {
637  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
638  DEV_ASSERT(rxBuff != NULL);
639 
640  status_t status, retVal = STATUS_SUCCESS;
641  LPUART_Type * base = s_lpuartBase[instance];
642  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
643 
644  while (rxSize > 0U)
645  {
646  while (!LPUART_GetStatusFlag(base, LPUART_RX_DATA_REG_FULL))
647  {}
648 
649  lpuartState->rxBuff = rxBuff;
650  LPUART_DRV_GetData(instance);
651 
652  if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
653  {
654  ++rxBuff;
655  --rxSize;
656  }
657  else
658  {
659  ++rxBuff;
660  ++rxBuff;
661  rxSize -= 2U;
662  }
663 
664  /* Clear the Overrun flag since it will block receiving */
665  if (LPUART_GetStatusFlag(base, LPUART_RX_OVERRUN))
666  {
667  status = LPUART_ClearStatusFlag(base, LPUART_RX_OVERRUN);
668  if (status != STATUS_SUCCESS)
669  {
670  retVal = STATUS_ERROR;
671  }
672  else
673  {
674  retVal = STATUS_UART_RX_OVERRUN;
675  }
676  }
677  }
678 
679  return retVal;
680 }
681 
682 /*FUNCTION**********************************************************************
683  *
684  * Function Name : LPUART_DRV_ReceiveData
685  * Description : This function receives data from LPUART module using
686  * non-blocking method. This function returns immediately after initiating the
687  * receive function. The application has to get the receive status to see when
688  * the receive is complete. In other words, after calling non-blocking get
689  * function, the application must get the receive status to check if receive
690  * is completed or not.
691  *
692  * Implements : LPUART_DRV_ReceiveData_Activity
693  *END**************************************************************************/
695  uint8_t * rxBuff,
696  uint32_t rxSize)
697 {
698  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
699  DEV_ASSERT(rxBuff != NULL);
700 
701  status_t retVal = STATUS_SUCCESS;
702  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
703 
704  /* Indicates this is a non-blocking transaction. */
705  lpuartState->isRxBlocking = false;
706 
707  DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
708  (lpuartState->transferType == LPUART_USING_DMA));
709 
710  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
711  {
712  /* Start the reception process using interrupts */
713  retVal = LPUART_DRV_StartReceiveDataUsingInt(instance, rxBuff, rxSize);
714  }
715 #if FEATURE_LPUART_HAS_DMA_ENABLE
716  else
717  {
718  /* Start the reception process using DMA */
719  retVal = LPUART_DRV_StartReceiveDataUsingDma(instance, rxBuff, rxSize);
720  }
721 #endif
722 
723  return retVal;
724 }
725 
726 /*FUNCTION**********************************************************************
727  *
728  * Function Name : LPUART_DRV_GetReceiveStatus
729  * Description : This function returns whether the previous LPUART receive is
730  * complete. When performing a non-blocking receive, the user can call this
731  * function to ascertain the state of the current receive progress: in progress
732  * or complete. In addition, if the receive is still in progress, the user can
733  * obtain the number of words that have been currently received.
734  *
735  * Implements : LPUART_DRV_GetReceiveStatus_Activity
736  *END**************************************************************************/
738  uint32_t * bytesRemaining)
739 {
740  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
741  DEV_ASSERT(bytesRemaining != NULL);
742 
743  const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
744 
745  if (lpuartState->isRxBusy)
746  {
747  /* Fill in the bytes transferred. */
748  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
749  {
750  /* In interrupt-based communication, the remaining bytes are retrieved
751  * from the state structure
752  */
753  *bytesRemaining = lpuartState->rxSize;
754  }
755 #if FEATURE_LPUART_HAS_DMA_ENABLE
756  else
757  {
758  /* In DMA-based communication, the remaining bytes are retrieved
759  * from the current DMA major loop count
760  */
761  *bytesRemaining = EDMA_DRV_GetRemainingMajorIterationsCount(lpuartState->rxDMAChannel);
762  }
763 #endif
764  }
765  else
766  {
767  *bytesRemaining = 0;
768  }
769 
770  return lpuartState->receiveStatus;
771 }
772 
773 /*FUNCTION**********************************************************************
774  *
775  * Function Name : LPUART_DRV_AbortReceivingData
776  * Description : Terminates a non-blocking receive early.
777  *
778  * Implements : LPUART_DRV_AbortReceivingData_Activity
779  *END**************************************************************************/
781 {
782  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
783 
784  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
785 
786  /* Check if a transfer is running. */
787  if (!lpuartState->isRxBusy)
788  {
789  return STATUS_SUCCESS;
790  }
791 
792  /* Stop the running transfer. */
793  if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
794  {
795  lpuartState->receiveStatus = STATUS_UART_ABORTED;
797  }
798 #if FEATURE_LPUART_HAS_DMA_ENABLE
799  else
800  {
801  lpuartState->receiveStatus = STATUS_UART_ABORTED;
802  LPUART_DRV_CompleteReceiveDataUsingDma(((void *)instance), EDMA_CHN_NORMAL);
803  }
804 #endif
805 
806  return STATUS_SUCCESS;
807 }
808 
809 /*FUNCTION**********************************************************************
810  *
811  * Function Name : LPUART_DRV_SetBaudRate
812  * Description : Configures the LPUART baud rate.
813  * In some LPUART instances the user must disable the transmitter/receiver
814  * before calling this function.
815  * Generally, this may be applied to all LPUARTs to ensure safe operation.
816  *
817  * Implements : LPUART_DRV_SetBaudRate_Activity
818  *END**************************************************************************/
819 status_t LPUART_DRV_SetBaudRate(uint32_t instance, uint32_t desiredBaudRate)
820 {
821  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
822 
823  uint16_t sbr, sbrTemp, i;
824  uint32_t osr, tempDiff, calculatedBaud, baudDiff;
825  uint32_t lpuartSourceClock;
826  clock_names_t instanceClkName = s_lpuartClkNames[instance];
827  LPUART_Type * base = s_lpuartBase[instance];
828 
829  /* Get the LPUART clock as configured in the clock manager */
830  (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);
831 
832  /* Check if current instance is clock gated off. */
833  DEV_ASSERT(lpuartSourceClock > 0U);
834 
835  /* This lpuart instantiation uses a slightly different baud rate calculation
836  * The idea is to use the best OSR (over-sampling rate) possible
837  * Note, osr is typically hard-set to 16 in other lpuart instantiations
838  * First calculate the baud rate using the minimum OSR possible (4) */
839  osr = 4;
840  sbr = (uint16_t)(lpuartSourceClock / (desiredBaudRate * osr));
841  calculatedBaud = (lpuartSourceClock / (osr * sbr));
842 
843  if (calculatedBaud > desiredBaudRate)
844  {
845  baudDiff = calculatedBaud - desiredBaudRate;
846  }
847  else
848  {
849  baudDiff = desiredBaudRate - calculatedBaud;
850  }
851 
852  /* loop to find the best osr value possible, one that generates minimum baudDiff
853  * iterate through the rest of the supported values of osr */
854  for (i = 5U; i <= 32U; i++)
855  {
856  /* calculate the temporary sbr value */
857  sbrTemp = (uint16_t)(lpuartSourceClock / (desiredBaudRate * i));
858  /* calculate the baud rate based on the temporary osr and sbr values */
859  calculatedBaud = (lpuartSourceClock / (i * sbrTemp));
860 
861  if (calculatedBaud > desiredBaudRate)
862  {
863  tempDiff = calculatedBaud - desiredBaudRate;
864  }
865  else
866  {
867  tempDiff = desiredBaudRate - calculatedBaud;
868  }
869 
870  if (tempDiff <= baudDiff)
871  {
872  baudDiff = tempDiff;
873  osr = i; /* update and store the best osr value calculated */
874  sbr = sbrTemp; /* update store the best sbr value calculated */
875  }
876  }
877 
878  /* Check if osr is between 4x and 7x oversampling.
879  * If so, then "BOTHEDGE" sampling must be turned on */
880  if ((osr > 3U) && (osr < 8U))
881  {
882  LPUART_SetBothEdgeSamplingCmd(base, true);
883  }
884 
885  /* program the osr value (bit value is one less than actual value) */
886  LPUART_SetOversamplingRatio(base, (osr - 1U));
887 
888  /* write the sbr value to the BAUD registers */
889  LPUART_SetBaudRateDivisor(base, sbr);
890 
891  return STATUS_SUCCESS;
892 }
893 
894 /*FUNCTION**********************************************************************
895  *
896  * Function Name : LPUART_DRV_GetBaudRate
897  * Description : Returns the LPUART configured baud rate.
898  *
899  * Implements : LPUART_DRV_GetBaudRate_Activity
900  *END**************************************************************************/
901 void LPUART_DRV_GetBaudRate(uint32_t instance, uint32_t * configuredBaudRate)
902 {
903  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
904 
905  uint8_t osr;
906  uint16_t sbr;
907  uint32_t lpuartSourceClock;
908  clock_names_t instanceClkName = s_lpuartClkNames[instance];
909  const LPUART_Type * base = s_lpuartBase[instance];
910 
911  /* Get the LPUART clock as configured in the clock manager */
912  (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);
913 
914  osr = LPUART_GetOversamplingRatio(base);
915  sbr = LPUART_GetBaudRateDivisor(base);
916 
917  *configuredBaudRate = (lpuartSourceClock / ((osr + 1UL) * sbr));
918 }
919 
920 /*FUNCTION**********************************************************************
921  *
922  * Function Name : LPUART_DRV_IRQHandler
923  * Description : Interrupt handler for LPUART.
924  * This handler uses the buffers stored in the lpuart_state_t structs to transfer
925  * data. This is not a public API as it is called by IRQ whenever an interrupt
926  * occurs.
927  *
928  *END**************************************************************************/
929 void LPUART_DRV_IRQHandler(uint32_t instance)
930 {
931  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
932 
933  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
934  LPUART_Type * base = s_lpuartBase[instance];
935 
936  /* Exit the ISR if no transfer is happening for this instance. */
937  if (!lpuartState->isTxBusy)
938  {
939  if (!lpuartState->isRxBusy)
940  {
941  return;
942  }
943  }
944 
945  /* Handle receive data full interrupt */
946  if (LPUART_GetIntMode(base, LPUART_INT_RX_DATA_REG_FULL))
947  {
948  if (LPUART_GetStatusFlag(base, LPUART_RX_DATA_REG_FULL))
949  {
950  /* Invoke callback if there is one */
951  if (lpuartState->rxCallback != NULL)
952  {
953  lpuartState->rxCallback(lpuartState, UART_EVENT_RX_FULL, lpuartState->rxCallbackParam);
954  }
955  else
956  {
957  /* Get data and put in receive buffer */
958  LPUART_DRV_GetData(instance);
959 
960  /* Update the internal state */
961  if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
962  {
963  ++lpuartState->rxBuff;
964  --lpuartState->rxSize;
965  }
966  else
967  {
968  ++lpuartState->rxBuff;
969  ++lpuartState->rxBuff;
970  lpuartState->rxSize -= 2U;
971  }
972 
973  /* Finish reception if this was the last byte received */
974  if (lpuartState->rxSize == 0U)
975  {
976  /* Complete transfer, will disable rx interrupt */
978  }
979  }
980  }
981  }
982 
983  /* Handle transmitter data register empty interrupt */
984  if (LPUART_GetIntMode(base, LPUART_INT_TX_DATA_REG_EMPTY))
985  {
986  if (LPUART_GetStatusFlag(base, LPUART_TX_DATA_REG_EMPTY))
987  {
988  /* Check if there are any more bytes to send */
989  if (lpuartState->txSize > 0U)
990  {
991  /* Invoke callback if there is one */
992  if (lpuartState->txCallback != NULL)
993  {
994  lpuartState->txCallback(lpuartState, UART_EVENT_TX_EMPTY, lpuartState->txCallbackParam);
995  }
996  else
997  {
998  /* Transmit the data */
999  LPUART_DRV_PutData(instance);
1000 
1001  /* Update the internal state */
1002  if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
1003  {
1004  ++lpuartState->txBuff;
1005  --lpuartState->txSize;
1006  }
1007  else
1008  {
1009  ++lpuartState->txBuff;
1010  ++lpuartState->txBuff;
1011  lpuartState->txSize -= 2U;
1012  }
1013 
1014  /* Finish the transmission if this was the last byte */
1015  if (lpuartState->txSize == 0U)
1016  {
1017  /* Complete transfer, will disable tx interrupt */
1019  }
1020  }
1021  }
1022  }
1023  }
1024 
1025  /* Handle receive overrun interrupt */
1026  if (LPUART_GetStatusFlag(base, LPUART_RX_OVERRUN))
1027  {
1028  lpuartState->receiveStatus = STATUS_UART_RX_OVERRUN;
1029  /* Clear the flag, OR the rxDataRegFull will not be set any more */
1030  (void)LPUART_ClearStatusFlag(base, LPUART_RX_OVERRUN);
1031  }
1032 }
1033 
1034 /*FUNCTION**********************************************************************
1035  *
1036  * Function Name : LPUART_DRV_StartSendDataUsingInt
1037  * Description : Initiate (start) a transmit by beginning the process of
1038  * sending data and enabling the interrupt.
1039  * This is not a public API as it is called from other driver functions.
1040  *
1041  *END**************************************************************************/
1043  const uint8_t * txBuff,
1044  uint32_t txSize)
1045 {
1046  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1047  DEV_ASSERT(txBuff != NULL);
1048 
1049  LPUART_Type * base = s_lpuartBase[instance];
1050  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1051 
1052  /* Check it's not busy transmitting data from a previous function call */
1053  if (lpuartState->isTxBusy)
1054  {
1055  return STATUS_BUSY;
1056  }
1057 
1058  /* Check the validity of the parameters */
1059  DEV_ASSERT(txSize > 0U);
1061  ((txSize & 1U) == 0U));
1062 
1063  /* initialize the module driver state structure */
1064  lpuartState->txBuff = txBuff;
1065  lpuartState->txSize = txSize;
1066  lpuartState->isTxBusy = true;
1067  lpuartState->transmitStatus = STATUS_BUSY;
1068 
1069  /* enable transmission complete interrupt */
1070  LPUART_SetIntMode(base, LPUART_INT_TX_DATA_REG_EMPTY, true);
1071 
1072  return STATUS_SUCCESS;
1073 }
1074 
1075 #if FEATURE_LPUART_HAS_DMA_ENABLE
1076 /*FUNCTION**********************************************************************
1077  *
1078  * Function Name : LPUART_DRV_StartSendDataUsingDma
1079  * Description : Initiate (start) a transmit by beginning the process of
1080  * sending data using DMA transfers.
1081  * This is not a public API as it is called from other driver functions.
1082  *
1083  *END**************************************************************************/
1084 static status_t LPUART_DRV_StartSendDataUsingDma(uint32_t instance,
1085  const uint8_t * txBuff,
1086  uint32_t txSize)
1087 {
1088  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1089  DEV_ASSERT(txBuff != NULL);
1090 
1091  LPUART_Type * base = s_lpuartBase[instance];
1092  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1093 
1094  /* Check it's not busy transmitting data from a previous function call */
1095  if (lpuartState->isTxBusy)
1096  {
1097  return STATUS_BUSY;
1098  }
1099 
1100  DEV_ASSERT(txSize > 0U);
1101 
1102  /* Update state structure */
1103  lpuartState->txBuff = txBuff;
1104  lpuartState->isTxBusy = true;
1105  lpuartState->transmitStatus = STATUS_BUSY;
1106 
1107  /* Configure the transfer control descriptor for the previously allocated channel */
1108  (void)EDMA_DRV_ConfigMultiBlockTransfer(lpuartState->txDMAChannel, EDMA_TRANSFER_MEM2PERIPH, (uint32_t)txBuff,
1109  (uint32_t)(&(base->DATA)), EDMA_TRANSFER_SIZE_1B, 1U, txSize, true);
1110 
1111  /* Call driver function to end the transmission when the DMA transfer is done */
1112  (void)EDMA_DRV_InstallCallback(lpuartState->txDMAChannel,
1113  (edma_callback_t)(LPUART_DRV_CompleteSendDataUsingDma),
1114  (void*)(instance));
1115 
1116  /* Start the DMA channel */
1117  (void)EDMA_DRV_StartChannel(lpuartState->txDMAChannel);
1118 
1119  /* Enable tx DMA requests for the current instance */
1120  LPUART_SetTxDmaCmd(base, true);
1121 
1122  return STATUS_SUCCESS;
1123 }
1124 #endif
1125 
1126 /*FUNCTION**********************************************************************
1127  *
1128  * Function Name : LPUART_DRV_CompleteSendDataUsingInt
1129  * Description : Finish up a transmit by completing the process of sending
1130  * data and disabling the interrupt.
1131  * This is not a public API as it is called from other driver functions.
1132  *
1133  *END**************************************************************************/
1134 static void LPUART_DRV_CompleteSendDataUsingInt(uint32_t instance)
1135 {
1136  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1137 
1138  LPUART_Type * base = s_lpuartBase[instance];
1139  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1140 
1141  /* Disable transmission complete interrupt */
1142  LPUART_SetIntMode(base, LPUART_INT_TX_DATA_REG_EMPTY, false);
1143 
1144  /* Signal the synchronous completion object. */
1145  if (lpuartState->isTxBlocking)
1146  {
1147  (void)OSIF_SemaPost(&lpuartState->txComplete);
1148  }
1149 
1150  /* Update the information of the module driver state */
1151  lpuartState->isTxBusy = false;
1152  lpuartState->transmitStatus = STATUS_SUCCESS;
1153 }
1154 
1155 #if FEATURE_LPUART_HAS_DMA_ENABLE
1156 /*FUNCTION**********************************************************************
1157  *
1158  * Function Name : LPUART_DRV_CompleteSendDataUsingDma
1159  * Description : Finish up a transmit by completing the process of sending
1160  * data and disabling the DMA requests. This is a callback for DMA major loop
1161  * completion, so it must match the DMA callback signature.
1162  * This is not a public API as it is called from other driver functions.
1163  *
1164  *END**************************************************************************/
1165 static void LPUART_DRV_CompleteSendDataUsingDma(void * parameter, edma_chn_status_t status)
1166 {
1167  if (status != EDMA_CHN_NORMAL)
1168  {
1169  return;
1170  }
1171 
1172  uint32_t instance = ((uint32_t)parameter);
1173  LPUART_Type * base = s_lpuartBase[instance];
1174  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1175 
1176  /* Disable tx DMA requests for the current instance */
1177  LPUART_SetTxDmaCmd(base, false);
1178 
1179  /* Release the DMA channel */
1180  (void)EDMA_DRV_StopChannel(lpuartState->txDMAChannel);
1181 
1182  /* Invoke callback if there is one */
1183  if (lpuartState->txCallback != NULL)
1184  {
1185  /* Pass the state structure as parameter for internal information retrieval */
1186  lpuartState->txCallback(lpuartState, UART_EVENT_END_TRANSFER, lpuartState->txCallbackParam);
1187  }
1188 
1189  /* Signal the synchronous completion object. */
1190  if (lpuartState->isTxBlocking)
1191  {
1192  (void)OSIF_SemaPost(&lpuartState->txComplete);
1193  }
1194 
1195  /* Update the information of the module driver state */
1196  lpuartState->isTxBusy = false;
1197  lpuartState->transmitStatus = STATUS_SUCCESS;
1198 }
1199 #endif
1200 
1201 /*FUNCTION**********************************************************************
1202  *
1203  * Function Name : LPUART_DRV_StartReceiveDataUsingInt
1204  * Description : Initiate (start) a receive by beginning the process of
1205  * receiving data and enabling the interrupt.
1206  * This is not a public API as it is called from other driver functions.
1207  *
1208  *END**************************************************************************/
1210  uint8_t * rxBuff,
1211  uint32_t rxSize)
1212 {
1213  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1214  DEV_ASSERT(rxBuff != NULL);
1215 
1216  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1217  LPUART_Type * base = s_lpuartBase[instance];
1218 
1219  /* Check it's not busy receiving data from a previous function call */
1220  if ((lpuartState->isRxBusy) && (!lpuartState->rxCallback))
1221  {
1222  return STATUS_BUSY;
1223  }
1224 
1225  /* Check the validity of the parameters */
1226  DEV_ASSERT(rxSize > 0U);
1228  ((rxSize & 1U) == 0U));
1229 
1230  /* Initialize the module driver state struct to indicate transfer in progress
1231  * and with the buffer and byte count data. */
1232  lpuartState->isRxBusy = true;
1233  lpuartState->rxBuff = rxBuff;
1234  lpuartState->rxSize = rxSize;
1235  lpuartState->receiveStatus = STATUS_BUSY;
1236 
1237  /* Enable the receive data overrun interrupt */
1238  LPUART_SetIntMode(base, LPUART_INT_RX_OVERRUN, true);
1239 
1240  /* Enable receive data full interrupt */
1241  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, true);
1242 
1243  return STATUS_SUCCESS;
1244 }
1245 
1246 #if FEATURE_LPUART_HAS_DMA_ENABLE
1247 /*FUNCTION**********************************************************************
1248  *
1249  * Function Name : LPUART_DRV_StartReceiveDataUsingDma
1250  * Description : Initiate (start) a receive by beginning the process of
1251  * receiving data using DMA transfers.
1252  * This is not a public API as it is called from other driver functions.
1253  *
1254  *END**************************************************************************/
1255 static status_t LPUART_DRV_StartReceiveDataUsingDma(uint32_t instance,
1256  uint8_t * rxBuff,
1257  uint32_t rxSize)
1258 {
1259  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1260  DEV_ASSERT(rxBuff != NULL);
1261 
1262  LPUART_Type * base = s_lpuartBase[instance];
1263  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1264 
1265  /* Check it's not busy transmitting data from a previous function call */
1266  if (lpuartState->isRxBusy)
1267  {
1268  return STATUS_BUSY;
1269  }
1270 
1271  DEV_ASSERT(rxSize > 0U);
1272 
1273  /* Configure the transfer control descriptor for the previously allocated channel */
1274  (void)EDMA_DRV_ConfigMultiBlockTransfer(lpuartState->rxDMAChannel, EDMA_TRANSFER_PERIPH2MEM,
1275  (uint32_t)(&(base->DATA)), (uint32_t)rxBuff, EDMA_TRANSFER_SIZE_1B,
1276  1U, rxSize, true);
1277 
1278  /* Call driver function to end the reception when the DMA transfer is done */
1279  (void)EDMA_DRV_InstallCallback(lpuartState->rxDMAChannel,
1280  (edma_callback_t)(LPUART_DRV_CompleteReceiveDataUsingDma),
1281  (void*)(instance));
1282 
1283  /* Start the DMA channel */
1284  (void)EDMA_DRV_StartChannel(lpuartState->rxDMAChannel);
1285 
1286  /* Enable rx DMA requests for the current instance */
1287  LPUART_SetRxDmaCmd(base, true);
1288 
1289  /* Update the state structure */
1290  lpuartState->rxBuff = rxBuff;
1291  lpuartState->isRxBusy = true;
1292  lpuartState->receiveStatus = STATUS_BUSY;
1293 
1294  /* Enable rx overrun interrupt, so the irq handler can clear the flag;
1295  * otherwise the receiver state machine may freeze on overrun condition
1296  */
1297  LPUART_SetIntMode(base, LPUART_INT_RX_OVERRUN, true);
1298 
1299  return STATUS_SUCCESS;
1300 }
1301 #endif
1302 
1303 /*FUNCTION**********************************************************************
1304  *
1305  * Function Name : LPUART_DRV_CompleteReceiveDataUsingInt
1306  * Description : Finish up a receive by completing the process of receiving data
1307  * and disabling the interrupt.
1308  * This is not a public API as it is called from other driver functions.
1309  *
1310  *END**************************************************************************/
1311 static void LPUART_DRV_CompleteReceiveDataUsingInt(uint32_t instance)
1312 {
1313  DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
1314 
1315  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1316  LPUART_Type * base = s_lpuartBase[instance];
1317 
1318  /* disable receive data full and rx overrun interrupt. */
1319  LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, false);
1320  LPUART_SetIntMode(base, LPUART_INT_RX_OVERRUN, false);
1321 
1322  /* Signal the synchronous completion object. */
1323  if (lpuartState->isRxBlocking)
1324  {
1325  (void)OSIF_SemaPost(&lpuartState->rxComplete);
1326  }
1327 
1328  /* Update the information of the module driver state */
1329  lpuartState->isRxBusy = false;
1330  lpuartState->receiveStatus = STATUS_SUCCESS;
1331 }
1332 
1333 #if FEATURE_LPUART_HAS_DMA_ENABLE
1334 /*FUNCTION**********************************************************************
1335  *
1336  * Function Name : LPUART_DRV_CompleteReceiveDataUsingDma
1337  * Description : Finish up a receive by completing the process of receiving data
1338  * and disabling the DMA requests. This is a callback for DMA major loop
1339  * completion, so it must match the DMA callback signature.
1340  * This is not a public API as it is called from other driver functions.
1341  *
1342  *END**************************************************************************/
1343 static void LPUART_DRV_CompleteReceiveDataUsingDma(void * parameter, edma_chn_status_t status)
1344 {
1345  if (status != EDMA_CHN_NORMAL)
1346  {
1347  return;
1348  }
1349 
1350  uint32_t instance = ((uint32_t)parameter);
1351  LPUART_Type * base = s_lpuartBase[instance];
1352  lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1353 
1354  /* Disable rx DMA requests for the current instance */
1355  LPUART_SetRxDmaCmd(base, false);
1356 
1357  /* Release the DMA channel */
1358  (void)EDMA_DRV_StopChannel(lpuartState->rxDMAChannel);
1359  LPUART_SetIntMode(base, LPUART_INT_RX_OVERRUN, false);
1360 
1361  /* Invoke callback if there is one */
1362  if (lpuartState->rxCallback != NULL)
1363  {
1364  lpuartState->rxCallback(lpuartState, UART_EVENT_END_TRANSFER, lpuartState->rxCallbackParam);
1365  }
1366 
1367  /* Signal the synchronous completion object. */
1368  if (lpuartState->isRxBlocking)
1369  {
1370  (void)OSIF_SemaPost(&lpuartState->rxComplete);
1371  }
1372 
1373  /* Update the information of the module driver state */
1374  lpuartState->isRxBusy = false;
1375  lpuartState->receiveStatus = STATUS_SUCCESS;
1376 }
1377 #endif
1378 
1379 /*FUNCTION**********************************************************************
1380  *
1381  * Function Name : LPUART_DRV_PutData
1382  * Description : Write data to the buffer register, according to configured
1383  * word length.
1384  * This is not a public API as it is called from other driver functions.
1385  *
1386  *END**************************************************************************/
1387 static void LPUART_DRV_PutData(uint32_t instance)
1388 {
1389  const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1390  LPUART_Type * base = s_lpuartBase[instance];
1391  uint16_t data;
1392  const uint8_t *txBuff = lpuartState->txBuff;
1393 
1394  if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
1395  {
1396  /* Transmit the data */
1397  LPUART_Putchar(base, *txBuff);
1398  }
1399  else if (lpuartState->bitCountPerChar == LPUART_9_BITS_PER_CHAR)
1400  {
1401  /* Create a 16-bits integer from two bytes */
1402  data = (uint16_t)(*txBuff);
1403  ++txBuff;
1404  data |= (uint16_t)(((uint16_t)(*txBuff)) << 8U);
1405 
1406  /* Transmit the data */
1407  LPUART_Putchar9(base, data);
1408  }
1409  else
1410  {
1411  /* Create a 16-bits integer from two bytes */
1412  data = (uint16_t)(*txBuff);
1413  ++txBuff;
1414  data |= (uint16_t)(((uint16_t)(*txBuff)) << 8U);
1415 
1416  /* Transmit the data */
1417  LPUART_Putchar10(base, data);
1418  }
1419 }
1420 
1421 /*FUNCTION**********************************************************************
1422  *
1423  * Function Name : LPUART_DRV_GetData
1424  * Description : Read data from the buffer register, according to configured
1425  * word length.
1426  * This is not a public API as it is called from other driver functions.
1427  *
1428  *END**************************************************************************/
1429 static void LPUART_DRV_GetData(uint32_t instance)
1430 {
1431  const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
1432  const LPUART_Type * base = s_lpuartBase[instance];
1433  uint16_t data;
1434  uint8_t *rxBuff = lpuartState->rxBuff;
1435 
1436  if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
1437  {
1438  /* Receive the data */
1439  LPUART_Getchar(base, rxBuff);
1440  }
1441  else if (lpuartState->bitCountPerChar == LPUART_9_BITS_PER_CHAR)
1442  {
1443  /* Receive the data */
1444  LPUART_Getchar9(base, &data);
1445 
1446  /* Write the least significant bits to the receive buffer */
1447  *rxBuff = (uint8_t)(data & 0xFFU);
1448  ++rxBuff;
1449  /* Write the ninth bit to the subsequent byte in the rx buffer */
1450  *rxBuff = (uint8_t)(data >> 8U);
1451  }
1452  else
1453  {
1454  /* Receive the data */
1455  LPUART_Getchar10(base, &data);
1456 
1457  /* Write the least significant bits to the receive buffer */
1458  *rxBuff = (uint8_t)(data & 0xFFU);
1459  ++rxBuff;
1460  /* Write the ninth and tenth bits to the subsequent byte in the rx buffer */
1461  *rxBuff = (uint8_t)(data >> 8U);
1462  }
1463 }
1464 
1465 /*******************************************************************************
1466  * EOF
1467  ******************************************************************************/
status_t LPUART_DRV_AbortSendingData(uint32_t instance)
Terminates a non-blocking transmission early.
static void LPUART_DRV_CompleteReceiveDataUsingInt(uint32_t instance)
#define LPUART_BASE_PTRS
Definition: S32K142.h:6630
status_t LPUART_DRV_SendDataBlocking(uint32_t instance, const uint8_t *txBuff, uint32_t txSize, uint32_t timeout)
Sends data out through the LPUART module using a blocking method.
static void LPUART_DRV_GetData(uint32_t instance)
uart_callback_t LPUART_DRV_InstallTxCallback(uint32_t instance, uart_callback_t function, void *callbackParam)
Installs callback function for the LPUART transmit.
void LPUART_DRV_SendDataPolling(uint32_t instance, const uint8_t *txBuff, uint32_t txSize)
Send out multiple bytes of data using polling method.
static LPUART_Type *const s_lpuartBase[LPUART_INSTANCE_COUNT]
Definition: lpuart_driver.c:94
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
status_t LPUART_DRV_Deinit(uint32_t instance)
Shuts down the LPUART by disabling interrupts and transmitter/receiver.
uint32_t EDMA_DRV_GetRemainingMajorIterationsCount(uint8_t channel)
Returns the remaining major loop iteration count.
Definition: edma_driver.c:1141
status_t LPUART_DRV_SendData(uint32_t instance, const uint8_t *txBuff, uint32_t txSize)
Sends data out through the LPUART module using a non-blocking method. This enables an a-sync method f...
static const IRQn_Type s_lpuartRxTxIrqId[LPUART_INSTANCE_COUNT]
Definition: lpuart_driver.c:97
volatile bool isRxBlocking
void DefaultISR(void)
Default ISR.
void * txCallbackParam
status_t LPUART_DRV_AbortReceivingData(uint32_t instance)
Terminates a non-blocking receive early.
uart_callback_t rxCallback
status_t EDMA_DRV_StopChannel(uint8_t channel)
Stops the eDMA channel.
Definition: edma_driver.c:838
status_t LPUART_DRV_ReceiveDataPolling(uint32_t instance, uint8_t *rxBuff, uint32_t rxSize)
Receive multiple bytes of data using polling method.
volatile bool isRxBusy
Definition: lpuart_driver.h:99
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
semaphore_t rxComplete
static void LPUART_DRV_CompleteSendDataUsingInt(uint32_t instance)
void * rxCallbackParam
lpuart_bit_count_per_char_t bitCountPerChar
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
lpuart_transfer_type_t transferType
lpuart_parity_mode_t parityMode
#define DEV_ASSERT(x)
Definition: devassert.h:77
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:193
clock_names_t
Clock names.
status_t LPUART_DRV_ReceiveData(uint32_t instance, uint8_t *rxBuff, uint32_t rxSize)
Gets data from the LPUART module by using a non-blocking method. This enables an a-sync method for re...
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
static void LPUART_DRV_PutData(uint32_t instance)
void LPUART_DRV_IRQHandler(uint32_t instance)
uart_callback_t LPUART_DRV_InstallRxCallback(uint32_t instance, uart_callback_t function, void *callbackParam)
Installs callback function for the LPUART receive.
static const clock_names_t s_lpuartClkNames[LPUART_INSTANCE_COUNT]
semaphore_t txComplete
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
uint8_t * rxBuff
Definition: lpuart_driver.h:95
status_t LPUART_DRV_SetBaudRate(uint32_t instance, uint32_t desiredBaudRate)
Configures the LPUART baud rate.
__IO uint32_t DATA
Definition: S32K142.h:6607
const uint8_t * txBuff
Definition: lpuart_driver.h:94
status_t LPUART_DRV_Init(uint32_t instance, lpuart_state_t *lpuartStatePtr, const lpuart_user_config_t *lpuartUserConfig)
Initializes an LPUART operation instance.
uart_callback_t txCallback
static status_t LPUART_DRV_StartReceiveDataUsingInt(uint32_t instance, uint8_t *rxBuff, uint32_t rxSize)
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
status_t EDMA_DRV_StartChannel(uint8_t channel)
Starts an eDMA channel.
Definition: edma_driver.c:813
volatile status_t transmitStatus
status_t LPUART_DRV_ReceiveDataBlocking(uint32_t instance, uint8_t *rxBuff, uint32_t rxSize, uint32_t timeout)
Gets data from the LPUART module by using a blocking method. Blocking means that the function does no...
#define LPUART_CLOCK_NAMES
volatile uint32_t txSize
Definition: lpuart_driver.h:96
static status_t LPUART_DRV_StartSendDataUsingInt(uint32_t instance, const uint8_t *txBuff, uint32_t txSize)
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
volatile bool isTxBlocking
LPUART configuration structure.
#define LPUART_INSTANCE_COUNT
Definition: S32K142.h:6615
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
void(* uart_callback_t)(void *driverState, uart_event_t event, void *userData)
Definition: callbacks.h:58
volatile uint32_t rxSize
Definition: lpuart_driver.h:97
static lpuart_state_t * s_lpuartStatePtr[LPUART_INSTANCE_COUNT]
Definition: lpuart_driver.c:91
void(* edma_callback_t)(void *parameter, edma_chn_status_t status)
Definition for the eDMA channel callback function.
Definition: edma_driver.h:204
void LPUART_DRV_GetBaudRate(uint32_t instance, uint32_t *configuredBaudRate)
Returns the LPUART baud rate.
status_t LPUART_DRV_GetTransmitStatus(uint32_t instance, uint32_t *bytesRemaining)
Returns whether the previous transmit is complete.
lpuart_transfer_type_t transferType
void(* isr_t)(void)
Interrupt handler type.
lpuart_bit_count_per_char_t bitCountPerChar
volatile status_t receiveStatus
Runtime state of the LPUART driver.
Definition: lpuart_driver.h:92
status_t LPUART_DRV_GetReceiveStatus(uint32_t instance, uint32_t *bytesRemaining)
Returns whether the previous receive is complete.
status_t EDMA_DRV_ConfigMultiBlockTransfer(uint8_t channel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t blockSize, uint32_t blockCount, bool disableReqOnCompletion)
Configures a multiple block data transfer with DMA.
Definition: edma_driver.c:589
status_t EDMA_DRV_InstallCallback(uint8_t channel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:293
volatile bool isTxBusy
Definition: lpuart_driver.h:98
#define LPUART_RX_TX_IRQS
Definition: S32K142.h:6636
isr_t g_lpuartIsr[LPUART_INSTANCE_COUNT]
Definition: lpuart_irq.c:72
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K142.h:192
void INT_SYS_InstallHandler(IRQn_Type irqNumber, const isr_t newHandler, isr_t *const oldHandler)
Installs an interrupt handler routine for a given IRQ number.
lpuart_stop_bit_count_t stopBitCount