S32 SDK
flexio_uart_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 - 2016, 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 
19 #include "flexio_uart_driver.h"
20 #include "flexio_hw_access.h"
21 #include "flexio_common.h"
22 #include "clock_manager.h"
23 
84 /*******************************************************************************
85  * Variables
86  ******************************************************************************/
87 
90 /* Constraints used for baud rate computation */
91 /* Divider minimum value is 0 for UART, so there is no point defining it */
92 #define DIVIDER_MAX_VALUE 0xFFU
93 
94 /* Shifters/Timers used for UART simulation The parameter x represents the
95  resourceIndex value for the current driver instance */
96 #define TX_SHIFTER(x) (x)
97 #define RX_SHIFTER(x) (x)
98 #define TX_TIMER(x) (x)
99 #define RX_TIMER(x) (x)
100 
101 /*******************************************************************************
102  * Private Functions
103  ******************************************************************************/
104 
105 
106 /*FUNCTION**********************************************************************
107  *
108  * Function Name : FLEXIO_UART_DRV_ComputeBaudRateDivider
109  * Description : Computes the baud rate divider for a target baud rate
110  *
111  *END**************************************************************************/
112 static void FLEXIO_UART_DRV_ComputeBaudRateDivider(flexio_uart_state_t *state,
113  uint32_t baudRate,
114  uint16_t *divider,
115  uint32_t inputClock)
116 {
117  uint32_t tmpDiv;
118 
119  (void)state;
120  /* Compute divider: ((input_clock / baud_rate) / 2) - 1. Round to nearest integer */
121  tmpDiv = ((inputClock + baudRate) / (2U * baudRate)) - 1U;
122  /* Enforce upper limit; lower limit is 0 for UART */
123  if (tmpDiv > DIVIDER_MAX_VALUE)
124  {
125  tmpDiv = DIVIDER_MAX_VALUE;
126  }
127 
128  *divider = (uint16_t)tmpDiv;
129 }
130 
131 
132 /*FUNCTION**********************************************************************
133  *
134  * Function Name : FLEXIO_UART_DRV_Configure
135  * Description : configures the FLEXIO module for UART
136  *
137  *END**************************************************************************/
138 static void FLEXIO_UART_DRV_ConfigureTx(flexio_uart_state_t *state,
139  const flexio_uart_user_config_t * userConfigPtr,
140  uint32_t inputClock)
141 {
142  FLEXIO_Type *baseAddr;
143  uint16_t divider;
144  uint16_t bits;
145  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
146 
147  baseAddr = g_flexioBase[state->flexioCommon.instance];
148  resourceIndex = state->flexioCommon.resourceIndex;
149 
150  /* Compute divider. */
151  FLEXIO_UART_DRV_ComputeBaudRateDivider(state, userConfigPtr->baudRate, &divider, inputClock);
152  bits = userConfigPtr->bitCount;
153 
154  /* Configure tx shifter */
155  FLEXIO_SetShifterConfig(baseAddr,
156  TX_SHIFTER(resourceIndex),
157  FLEXIO_SHIFTER_START_BIT_0,
158  FLEXIO_SHIFTER_STOP_BIT_1,
159  FLEXIO_SHIFTER_SOURCE_PIN);
160  FLEXIO_SetShifterControl(baseAddr,
161  TX_SHIFTER(resourceIndex),
162  FLEXIO_SHIFTER_MODE_TRANSMIT,
163  userConfigPtr->dataPin, /* output on tx pin */
164  FLEXIO_PIN_POLARITY_HIGH,
165  FLEXIO_PIN_CONFIG_OUTPUT,
166  TX_TIMER(resourceIndex),
167  FLEXIO_TIMER_POLARITY_POSEDGE);
168 
169  /* Configure tx timer */
170  FLEXIO_SetTimerCompare(baseAddr, TX_TIMER(resourceIndex), (uint16_t)((((bits << 1U) - 1U) << 8U) + divider));
171  FLEXIO_SetTimerConfig(baseAddr,
172  TX_TIMER(resourceIndex),
173  FLEXIO_TIMER_START_BIT_ENABLED,
174  FLEXIO_TIMER_STOP_BIT_TIM_DIS,
175  FLEXIO_TIMER_ENABLE_TRG_HIGH, /* enable when Tx data is available */
176  FLEXIO_TIMER_DISABLE_TIM_CMP,
177  FLEXIO_TIMER_RESET_NEVER,
178  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
179  FLEXIO_TIMER_INITOUT_ONE);
180  FLEXIO_SetTimerControl(baseAddr,
181  TX_TIMER(resourceIndex),
182  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
183  FLEXIO_TRIGGER_POLARITY_LOW,
184  FLEXIO_TRIGGER_SOURCE_INTERNAL,
185  0U, /* pin unused */
186  FLEXIO_PIN_POLARITY_HIGH,
187  FLEXIO_PIN_CONFIG_DISABLED,
188  FLEXIO_TIMER_MODE_DISABLED);
189  /* disable Tx shifter */
190  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
191 }
192 
193 
194 
195 /*FUNCTION**********************************************************************
196  *
197  * Function Name : FLEXIO_UART_DRV_Configure
198  * Description : configures the FLEXIO module for UART
199  *
200  *END**************************************************************************/
201 static void FLEXIO_UART_DRV_ConfigureRx(flexio_uart_state_t *state,
202  const flexio_uart_user_config_t * userConfigPtr,
203  uint32_t inputClock)
204 {
205  FLEXIO_Type *baseAddr;
206  uint16_t divider;
207  uint16_t bits;
208  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
209 
210  baseAddr = g_flexioBase[state->flexioCommon.instance];
211  resourceIndex = state->flexioCommon.resourceIndex;
212 
213  /* Compute divider. */
214  FLEXIO_UART_DRV_ComputeBaudRateDivider(state, userConfigPtr->baudRate, &divider, inputClock);
215  bits = userConfigPtr->bitCount;
216 
217  /* Configure rx shifter */
218  FLEXIO_SetShifterConfig(baseAddr,
219  RX_SHIFTER(resourceIndex),
220  FLEXIO_SHIFTER_START_BIT_0,
221  FLEXIO_SHIFTER_STOP_BIT_1,
222  FLEXIO_SHIFTER_SOURCE_PIN);
223  FLEXIO_SetShifterControl(baseAddr,
224  RX_SHIFTER(resourceIndex),
225  FLEXIO_SHIFTER_MODE_DISABLED,
226  userConfigPtr->dataPin, /* input from rx pin */
227  FLEXIO_PIN_POLARITY_HIGH,
228  FLEXIO_PIN_CONFIG_DISABLED,
229  RX_TIMER(resourceIndex),
230  FLEXIO_TIMER_POLARITY_NEGEDGE);
231 
232  /* Configure rx timer */
233  FLEXIO_SetTimerCompare(baseAddr, RX_TIMER(resourceIndex), (uint16_t)((((bits << 1U) - 1U) << 8U) + divider));
234  FLEXIO_SetTimerConfig(baseAddr,
235  RX_TIMER(resourceIndex),
236  FLEXIO_TIMER_START_BIT_ENABLED,
237  FLEXIO_TIMER_STOP_BIT_TIM_DIS,
238  FLEXIO_TIMER_ENABLE_PIN_POSEDGE, /* enable when data is available */
239  FLEXIO_TIMER_DISABLE_TIM_CMP,
240  FLEXIO_TIMER_RESET_PIN_RISING,
241  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
242  FLEXIO_TIMER_INITOUT_ONE_RESET);
243  FLEXIO_SetTimerControl(baseAddr,
244  RX_TIMER(resourceIndex),
245  0U, /* trigger unused */
246  FLEXIO_TRIGGER_POLARITY_HIGH,
247  FLEXIO_TRIGGER_SOURCE_EXTERNAL,
248  userConfigPtr->dataPin, /* input from rx pin */
249  FLEXIO_PIN_POLARITY_LOW,
250  FLEXIO_PIN_CONFIG_DISABLED,
251  FLEXIO_TIMER_MODE_DISABLED);
252 }
253 
254 
255 /*FUNCTION**********************************************************************
256  *
257  * Function Name : FLEXIO_UART_DRV_EndTransfer
258  * Description : End the current transfer
259  *
260  *END**************************************************************************/
261 static void FLEXIO_UART_DRV_EndTransfer(flexio_uart_state_t *state)
262 {
263  FLEXIO_Type *baseAddr;
264  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
265 
266  baseAddr = g_flexioBase[state->flexioCommon.instance];
267  resourceIndex = state->flexioCommon.resourceIndex;
268 
269  /* Disable transfer engine */
270  switch (state->driverType)
271  {
273  /* Disable interrupts for Rx / Tx shifter */
274  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
275  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
276  /* disable timer interrupt */
277  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << TX_TIMER(resourceIndex)), false);
278  break;
280  /* Nothing to do here */
281  break;
283  /* for Tx we need to disable timer interrupt */
284  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << TX_TIMER(resourceIndex)), false);
285  /* Stop DMA channels */
286  (void)EDMA_DRV_StopChannel(state->dmaChannel);
287  /* Disable the FlexIO DMA request */
288  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
289  break;
290  default:
291  /* Impossible type - do nothing */
292  break;
293  }
294 
295  state->driverIdle = true;
296  /* Signal transfer end for blocking transfers */
297  if (state->blocking == true)
298  {
299  (void)OSIF_SemaPost(&(state->idleSemaphore));
300  }
301 }
302 
303 
304 /*FUNCTION**********************************************************************
305  *
306  * Function Name : FLEXIO_UART_DRV_EnableTransfer
307  * Description : Enables timers and shifters to start a transfer
308  *
309  *END**************************************************************************/
310 static void FLEXIO_UART_DRV_EnableTransfer(flexio_uart_state_t *state)
311 {
312  FLEXIO_Type *baseAddr;
313  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
314 
315  resourceIndex = state->flexioCommon.resourceIndex;
316  baseAddr = g_flexioBase[state->flexioCommon.instance];
317 
318  /* Enable timers and shifters */
319  if (state->direction == FLEXIO_UART_DIRECTION_TX)
320  {
321  /* In tx mode restore start bit in case it was changed for end of transmission detection */
322  FLEXIO_SetShifterStartBit(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_START_BIT_0);
323  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_TRANSMIT);
324  }
325  else
326  {
327  /* In rx mode, discard any leftover rx. data */
328  FLEXIO_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
329  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_RECEIVE);
330  }
331  FLEXIO_SetTimerMode(baseAddr, TX_TIMER(resourceIndex), FLEXIO_TIMER_MODE_8BIT_BAUD);
332 }
333 
334 
335 /*FUNCTION**********************************************************************
336  *
337  * Function Name : FLEXIO_UART_DRV_StopTransfer
338  * Description : Forcefully stops the current transfer
339  *
340  *END**************************************************************************/
341 static void FLEXIO_UART_DRV_StopTransfer(flexio_uart_state_t *state)
342 {
343  FLEXIO_Type *baseAddr;
344  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
345 
346  resourceIndex = state->flexioCommon.resourceIndex;
347  baseAddr = g_flexioBase[state->flexioCommon.instance];
348 
349  /* disable and re-enable timers and shifters to reset them */
350  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
351  FLEXIO_SetTimerMode(baseAddr, TX_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
352 
353  /* clear any leftover error flags */
354  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
355 
356  /* end the transfer */
357  FLEXIO_UART_DRV_EndTransfer(state);
358 }
359 
360 
361 /*FUNCTION**********************************************************************
362  *
363  * Function Name : FLEXIO_UART_DRV_WaitTransferEnd
364  * Description : waits for the end of a blocking transfer
365  *
366  *END**************************************************************************/
367 static status_t FLEXIO_UART_DRV_WaitTransferEnd(flexio_uart_state_t *state, uint32_t timeout)
368 {
369  status_t osifError = STATUS_SUCCESS;
370 
371  switch (state->driverType)
372  {
374  /* Wait for transfer to be completed by the IRQ */
375  osifError = OSIF_SemaWait(&(state->idleSemaphore), timeout);
376  break;
378  /* Call FLEXIO_UART_DRV_GetStatus() to do the transfer */
379  while (FLEXIO_UART_DRV_GetStatus(state, NULL) == STATUS_BUSY) {}
380  break;
382  /* Wait for transfer completion to be signaled by the DMA or IRQ */
383  osifError = OSIF_SemaWait(&(state->idleSemaphore), timeout);
384  break;
385  default:
386  /* Impossible type - do nothing */
387  break;
388  }
389 
390  /* blocking transfer is over */
391  state->blocking = false;
392  if (osifError == STATUS_TIMEOUT)
393  {
394  /* abort current transfer */
395  state->status = STATUS_TIMEOUT;
396  FLEXIO_UART_DRV_StopTransfer(state);
397  }
398 
399  return state->status;
400 }
401 
402 
403 /*FUNCTION**********************************************************************
404  *
405  * Function Name : FLEXIO_UART_DRV_ReadData
406  * Description : reads data received by the module
407  *
408  *END**************************************************************************/
409 static void FLEXIO_UART_DRV_ReadData(flexio_uart_state_t *state)
410 {
411  const FLEXIO_Type *baseAddr;
412  uint32_t data;
413  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
414 
415  DEV_ASSERT(state->remainingBytes > 0U);
416  DEV_ASSERT(state->data != NULL);
417 
418  baseAddr = g_flexioBase[state->flexioCommon.instance];
419  resourceIndex = state->flexioCommon.resourceIndex;
420 
421  /* Read data from shifter buffer */
422  data = FLEXIO_ReadShifterBuffer(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_RW_MODE_NORMAL);
423  data >>= 32U - (uint32_t)(state->bitCount);
424 
425  if (state->bitCount <= 8U)
426  {
427  *(uint8_t *)state->data = (uint8_t)data;
428  /* Update rx buffer pointer and remaining bytes count */
429  state->data ++;
430  state->remainingBytes -= 1U;
431  }
432  else
433  {
434  /* for more than 8 bits per word 2 bytes are needed */
435  *(uint16_t *)state->data = (uint16_t)data;
436  /* Update rx buffer pointer and remaining bytes count */
437  state->data = &state->data[2U];
438  state->remainingBytes -= 2U;
439  }
440 }
441 
442 
443 /*FUNCTION**********************************************************************
444  *
445  * Function Name : FLEXIO_UART_DRV_WriteData
446  * Description : writes data to be transmitted by the module
447  *
448  *END**************************************************************************/
449 static void FLEXIO_UART_DRV_WriteData(flexio_uart_state_t *state)
450 {
451  FLEXIO_Type *baseAddr;
452  uint32_t data;
453  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
454 
455  DEV_ASSERT(state->data != NULL);
456 
457  baseAddr = g_flexioBase[state->flexioCommon.instance];
458  resourceIndex = state->flexioCommon.resourceIndex;
459 
460  if (state->remainingBytes == 0U)
461  {
462  /* Done transmitting */
463  return;
464  }
465  /* Read data from user buffer and update tx buffer pointer and remaining bytes count */
466  if (state->bitCount <= 8U)
467  {
468  data = (uint32_t)(*(uint8_t *)state->data);
469  state->data++;
470  state->remainingBytes -= 1U;
471  }
472  else
473  {
474  /* for more than 8 bits per word 2 bytes are needed */
475  data = (uint32_t)(*(uint16_t *)state->data);
476  state->data = &state->data[2U];
477  state->remainingBytes -= 2U;
478  }
479 
480  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), data, FLEXIO_SHIFTER_RW_MODE_NORMAL);
481 }
482 
483 
484 /*FUNCTION**********************************************************************
485  *
486  * Function Name : FLEXIO_UART_DRV_CheckStatusTx
487  * Description : Check status of the UART transmission. This function can be
488  * called either in an interrupt routine or directly in polling
489  * mode to advance the transfer.
490  *
491  *END**************************************************************************/
492 static void FLEXIO_UART_DRV_CheckStatusTx(void *stateStruct)
493 {
494  FLEXIO_Type *baseAddr;
495  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
496  flexio_uart_state_t *state;
497 
498  DEV_ASSERT(stateStruct != NULL);
499 
500  state = (flexio_uart_state_t *)stateStruct;
501  baseAddr = g_flexioBase[state->flexioCommon.instance];
502  resourceIndex = state->flexioCommon.resourceIndex;
503 
504  /* No need to check for Tx underflow since timer is controlled by the shifter status flag */
505  /* Check for transfer end */
506  if (state->remainingBytes == 0U)
507  {
508  if (FLEXIO_GetTimerStatus(baseAddr, TX_TIMER(resourceIndex)))
509  {
510  /* Clear timer status */
511  FLEXIO_ClearTimerStatus(baseAddr, TX_TIMER(resourceIndex));
512  state->txFlush--;
513  if (state->txFlush == 0U)
514  {
515  /* Done flushing the Tx buffer, end transfer */
516  /* Record success if there was no error */
517  if (state->status == STATUS_BUSY)
518  {
519  state->status = STATUS_SUCCESS;
520  }
521  FLEXIO_UART_DRV_StopTransfer(state);
522  /* Call callback to announce the end transfer event to the user */
523  if (state->callback != NULL)
524  {
525  state->callback(state, UART_EVENT_END_TRANSFER, state->callbackParam);
526  }
527  }
528  else if (FLEXIO_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)))
529  {
530  /* txFlush == 1, but last byte was already transferred from buffer to shifter. There is a
531  danger that the transmission is over and we end up never reporting the end event.
532  To avoid this, send one extra dummy byte */
533  /* set start bit to 1 and send an 0xFF byte, this way the line will appear idle */
534  FLEXIO_SetShifterStartBit(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_START_BIT_1);
535  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), 0xFFFFFFFFUL, FLEXIO_SHIFTER_RW_MODE_NORMAL);
536  }
537  else
538  {
539  /* txFlush == 1, and last byte was not yet transferred from buffer to shifter.
540  No need to do anything, just wait for the next timer event. */
541  }
542  }
543  }
544  /* Check if transmitter needs more data */
545  else if (FLEXIO_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)) && (state->remainingBytes > 0U))
546  {
547  FLEXIO_UART_DRV_WriteData(state);
548  if (state->remainingBytes == 0U)
549  {
550  /* Out of data, call callback to allow user to provide a new buffer */
551  if (state->callback != NULL)
552  {
553  state->callback(state, UART_EVENT_TX_EMPTY, state->callbackParam);
554  }
555  }
556  if (state->remainingBytes == 0U)
557  {
558  /* No more data, transmission will stop after the last bytes are sent.
559  The timer event will indicate when the send is complete */
560  /* clear any previous timer events */
561  FLEXIO_ClearTimerStatus(baseAddr, TX_TIMER(resourceIndex));
562  if (state->driverType == FLEXIO_DRIVER_TYPE_INTERRUPTS)
563  {
564  /* transmission completed; disable interrupt */
565  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
566  /* enable timer interrupt to ensure that transfer is completed */
567  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << TX_TIMER(resourceIndex)), true);
568  }
569  }
570  }
571  else
572  {
573  /* No relevant events - nothing to do */
574  }
575 
576 }
577 
578 /*FUNCTION**********************************************************************
579  *
580  * Function Name : FLEXIO_UART_DRV_CheckStatusRx
581  * Description : Check status of the UART reception. This function can be
582  * called either in an interrupt routine or directly in polling
583  * mode to advance the transfer.
584  *
585  *END**************************************************************************/
586 static void FLEXIO_UART_DRV_CheckStatusRx(void *stateStruct)
587 {
588  FLEXIO_Type *baseAddr;
589  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
590  flexio_uart_state_t *state;
591 
592  DEV_ASSERT(stateStruct != NULL);
593 
594  state = (flexio_uart_state_t *)stateStruct;
595  baseAddr = g_flexioBase[state->flexioCommon.instance];
596  resourceIndex = state->flexioCommon.resourceIndex;
597 
598  /* Check for errors */
599  if (FLEXIO_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
600  {
601  state->status = STATUS_UART_RX_OVERRUN;
602  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
603  state->remainingBytes = 0U;
604  /* Continue processing events */
605  }
606  /* Check if data was received */
607  else if (FLEXIO_GetShifterStatus(baseAddr, RX_SHIFTER(resourceIndex)))
608  {
609  FLEXIO_UART_DRV_ReadData(state);
610  if (state->remainingBytes == 0U)
611  {
612  /* Out of data, call callback to allow user to provide a new buffer */
613  if (state->callback != NULL)
614  {
615  state->callback(state, UART_EVENT_RX_FULL, state->callbackParam);
616  }
617  }
618  }
619  else
620  {
621  /* No events - nothing to do */
622  }
623  /* Check if transfer is over */
624  if (state->remainingBytes == 0U)
625  {
626  /* Record success if there was no error */
627  if (state->status == STATUS_BUSY)
628  {
629  state->status = STATUS_SUCCESS;
630  }
631  /* discard any leftover rx. data */
632  FLEXIO_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
633  /* End transfer */
634  FLEXIO_UART_DRV_StopTransfer(state);
635  /* Call callback to announce the event to the user */
636  if (state->callback != NULL)
637  {
638  state->callback(state, UART_EVENT_END_TRANSFER, state->callbackParam);
639  }
640  }
641 }
642 
643 /*FUNCTION**********************************************************************
644  *
645  * Function Name : FLEXIO_UART_DRV_CheckStatus
646  * Description : Check status of the UART transfer. This function can be
647  * called either in an interrupt routine or directly in polling
648  * mode to advance the transfer.
649  *
650  *END**************************************************************************/
651 static void FLEXIO_UART_DRV_CheckStatus(void *stateStruct)
652 {
653  const flexio_uart_state_t *state;
654 
655  DEV_ASSERT(stateStruct != NULL);
656 
657  state = (flexio_uart_state_t *)stateStruct;
658  if (state->direction == FLEXIO_UART_DIRECTION_TX)
659  {
660  FLEXIO_UART_DRV_CheckStatusTx(stateStruct);
661  }
662  else
663  {
664  FLEXIO_UART_DRV_CheckStatusRx(stateStruct);
665  }
666 }
667 
668 
669 /*FUNCTION**********************************************************************
670  *
671  * Function Name : FLEXIO_UART_DRV_EndDmaTxTransfer
672  * Description : function called at the end of a DMA Tx transfer
673  *
674  *END**************************************************************************/
675 static void FLEXIO_UART_DRV_EndDmaTxTransfer(void *stateStruct, edma_chn_status_t status)
676 {
677  flexio_uart_state_t *state;
678  uint8_t dmaChn;
679  uint32_t byteCount;
680  FLEXIO_Type *baseAddr;
681 
682  DEV_ASSERT(stateStruct != NULL);
683 
684  (void)status;
685  state = (flexio_uart_state_t *)stateStruct;
686  baseAddr = g_flexioBase[state->flexioCommon.instance];
687 
688  /* Call callback to allow user to provide a new buffer */
689  if (state->callback != NULL)
690  {
691  state->callback(state, UART_EVENT_TX_EMPTY, state->callbackParam);
692  }
693  if (state->remainingBytes == 0U)
694  {
695  /* No more data to transmit, transmission will stop */
696  /* enable timer interrupt to let IRQ ensure that transfer is completed */
697  FLEXIO_ClearTimerStatus(baseAddr, TX_TIMER(state->flexioCommon.resourceIndex));
698  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << TX_TIMER(state->flexioCommon.resourceIndex)), true);
699  }
700  else
701  {
702  /* There is more data to transfer, restart DMA channel */
703  /* Update buffer address and size */
704  dmaChn = state->dmaChannel;
705  if (state->bitCount <= 8U)
706  {
707  byteCount = 1U;
708  }
709  else
710  {
711  byteCount = 2U;
712  }
713  EDMA_DRV_SetSrcAddr(dmaChn, (uint32_t)(state->data));
714  EDMA_DRV_SetMajorLoopIterationCount(dmaChn, state->remainingBytes / byteCount);
715  /* Now that this tx is set up, clear remaining bytes count */
716  state->remainingBytes = 0U;
717  /* Start the channel */
718  (void)EDMA_DRV_StartChannel(dmaChn);
719  }
720 }
721 
722 
723 /*FUNCTION**********************************************************************
724  *
725  * Function Name : FLEXIO_UART_DRV_EndDmaRxTransfer
726  * Description : function called at the end of a DMA Rx transfer
727  *
728  *END**************************************************************************/
729 static void FLEXIO_UART_DRV_EndDmaRxTransfer(void *stateStruct, edma_chn_status_t status)
730 {
731  flexio_uart_state_t *state;
732  uint8_t dmaChn;
733  uint32_t byteCount;
734 
735  DEV_ASSERT(stateStruct != NULL);
736 
737  (void)status;
738  state = (flexio_uart_state_t *)stateStruct;
739 
740  /* Call callback to allow user to provide a new buffer */
741  if (state->callback != NULL)
742  {
743  state->callback(state, UART_EVENT_RX_FULL, state->callbackParam);
744  }
745  if (state->remainingBytes == 0U)
746  {
747  /* No more data to transmit, reception will stop */
748  state->status = STATUS_SUCCESS;
749  FLEXIO_UART_DRV_StopTransfer(state);
750  /* Call callback to announce the event to the user */
751  if (state->callback != NULL)
752  {
753  state->callback(state, UART_EVENT_END_TRANSFER, state->callbackParam);
754  }
755  }
756  else
757  {
758  /* There is more data to transfer, restart DMA channel */
759  /* Update buffer address and size */
760  dmaChn = state->dmaChannel;
761  if (state->bitCount <= 8U)
762  {
763  byteCount = 1U;
764  }
765  else
766  {
767  byteCount = 2U;
768  }
769  EDMA_DRV_SetDestAddr(dmaChn, (uint32_t)(state->data));
770  EDMA_DRV_SetMajorLoopIterationCount(dmaChn, state->remainingBytes / byteCount);
771  /* Now that this tx is set up, clear remaining bytes count */
772  state->remainingBytes = 0U;
773  /* Start the channel */
774  (void)EDMA_DRV_StartChannel(dmaChn);
775  }
776 }
777 
778 
779 
780 /*FUNCTION**********************************************************************
781  *
782  * Function Name : FLEXIO_UART_DRV_ComputeTxRegAddr
783  * Description : Computes the address of the register used for DMA tx transfer
784  *
785  *END**************************************************************************/
786 static uint32_t FLEXIO_UART_DRV_ComputeTxRegAddr(const flexio_uart_state_t *state)
787 {
788  uint32_t addr;
789  const FLEXIO_Type *baseAddr;
790  uint8_t shifter;
791 
792  baseAddr = g_flexioBase[state->flexioCommon.instance];
793  shifter = TX_SHIFTER(state->flexioCommon.resourceIndex);
794  addr = (uint32_t)(&(baseAddr->SHIFTBUF[shifter]));
795  return addr;
796 }
797 
798 
799 /*FUNCTION**********************************************************************
800  *
801  * Function Name : FLEXIO_UART_DRV_ComputeRxRegAddr
802  * Description : Computes the address of the register used for DMA rx transfer
803  *
804  *END**************************************************************************/
805 static uint32_t FLEXIO_UART_DRV_ComputeRxRegAddr(const flexio_uart_state_t *state)
806 {
807  uint32_t addr;
808  const FLEXIO_Type *baseAddr;
809  uint8_t shifter;
810  uint32_t byteCount;
811 
812  if (state->bitCount <= 8U)
813  {
814  byteCount = 1U;
815  }
816  else
817  {
818  byteCount = 2U;
819  }
820  baseAddr = g_flexioBase[state->flexioCommon.instance];
821  shifter = RX_SHIFTER(state->flexioCommon.resourceIndex);
822  addr = (uint32_t)(&(baseAddr->SHIFTBUF[shifter])) + (sizeof(uint32_t) - byteCount);
823  return addr;
824 }
825 
826 
827 /*FUNCTION**********************************************************************
828  *
829  * Function Name : FLEXIO_UART_DRV_StartTxDmaTransfer
830  * Description : Starts a Tx DMA transfer
831  *
832  *END**************************************************************************/
833 static void FLEXIO_UART_DRV_StartTxDmaTransfer(flexio_uart_state_t *state)
834 {
835  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
836  FLEXIO_Type *baseAddr;
837  edma_transfer_size_t dmaTransferSize;
838  uint32_t byteCount;
839 
840  baseAddr = g_flexioBase[state->flexioCommon.instance];
841  resourceIndex = state->flexioCommon.resourceIndex;
842 
843  /* Configure the transfer control descriptor for the previously allocated channel */
844  if (state->bitCount <= 8U)
845  {
846  dmaTransferSize = EDMA_TRANSFER_SIZE_1B;
847  byteCount = 1U;
848  }
849  else
850  {
851  dmaTransferSize = EDMA_TRANSFER_SIZE_2B;
852  byteCount = 2U;
853  }
854  (void)EDMA_DRV_ConfigMultiBlockTransfer(state->dmaChannel,
856  (uint32_t)(state->data),
857  FLEXIO_UART_DRV_ComputeTxRegAddr(state),
858  dmaTransferSize,
859  byteCount,
860  state->remainingBytes / byteCount,
861  true);
862 
863  /* Now that this transfer is set up, clear remaining bytes count */
864  state->remainingBytes = 0U;
865 
866  /* Setup callback for DMA tx transfer end */
867  (void)EDMA_DRV_InstallCallback(state->dmaChannel,
868  (edma_callback_t)(FLEXIO_UART_DRV_EndDmaTxTransfer),
869  (void*)(state));
870  /* Start tx DMA channel */
871  (void)EDMA_DRV_StartChannel(state->dmaChannel);
872 
873  /* Enable FlexIO DMA requests */
874  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), true);
875 }
876 
877 
878 /*FUNCTION**********************************************************************
879  *
880  * Function Name : FLEXIO_UART_DRV_StartRxDmaTransfer
881  * Description : Starts an Rx DMA transfer
882  *
883  *END**************************************************************************/
884 static void FLEXIO_UART_DRV_StartRxDmaTransfer(flexio_uart_state_t *state)
885 {
886  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
887  FLEXIO_Type *baseAddr;
888  edma_transfer_size_t dmaTransferSize;
889  uint32_t byteCount;
890 
891  baseAddr = g_flexioBase[state->flexioCommon.instance];
892  resourceIndex = state->flexioCommon.resourceIndex;
893 
894  /* Configure the transfer control descriptor for the previously allocated channel */
895  if (state->bitCount <= 8U)
896  {
897  dmaTransferSize = EDMA_TRANSFER_SIZE_1B;
898  byteCount = 1U;
899  }
900  else
901  {
902  dmaTransferSize = EDMA_TRANSFER_SIZE_2B;
903  byteCount = 2U;
904  }
905  (void)EDMA_DRV_ConfigMultiBlockTransfer(state->dmaChannel,
907  FLEXIO_UART_DRV_ComputeRxRegAddr(state),
908  (uint32_t)(state->data),
909  dmaTransferSize,
910  byteCount,
911  state->remainingBytes / byteCount,
912  true);
913 
914  /* Now that this transfer is set up, clear remaining bytes count */
915  state->remainingBytes = 0U;
916 
917  /* Setup callback for DMA tx transfer end */
918  (void)EDMA_DRV_InstallCallback(state->dmaChannel,
919  (edma_callback_t)(FLEXIO_UART_DRV_EndDmaRxTransfer),
920  (void*)(state));
921  /* Start tx DMA channel */
922  (void)EDMA_DRV_StartChannel(state->dmaChannel);
923 
924  /* Enable FlexIO DMA requests */
925  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), true);
926 }
927 
930 /*******************************************************************************
931  * Code
932  ******************************************************************************/
933 
934 /*FUNCTION**********************************************************************
935  *
936  * Function Name : FLEXIO_UART_DRV_Init
937  * Description : Initialize the FLEXIO_UART driver
938  * Implements : FLEXIO_UART_DRV_Init_Activity
939  *
940  *END**************************************************************************/
941 status_t FLEXIO_UART_DRV_Init(uint32_t instance,
942  const flexio_uart_user_config_t * userConfigPtr,
943  flexio_uart_state_t * state)
944 {
945  uint32_t inputClock;
946  status_t clkErr;
947  status_t retCode;
948  status_t osifError = STATUS_SUCCESS;
949  uint8_t dmaReq;
950 
951  DEV_ASSERT(state != NULL);
952  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
953  /* Check that device was initialized */
954  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
955 
956  /* Get the protocol clock frequency */
957  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[instance], &inputClock);
958  DEV_ASSERT(clkErr == STATUS_SUCCESS);
959  DEV_ASSERT(inputClock > 0U);
960 
961 
962  /* Instruct the resource allocator that we need one shifter/timer */
963  state->flexioCommon.resourceCount = 1U;
964  /* Common FlexIO driver initialization */
965  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)state);
966  if (retCode != STATUS_SUCCESS)
967  { /* Initialization failed, not enough resources */
968  return retCode;
969  }
970  /* Initialize the semaphore */
971  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
972  {
973  osifError = OSIF_SemaCreate(&(state->idleSemaphore), 0U);
974  DEV_ASSERT(osifError == STATUS_SUCCESS);
975  }
976 
977  /* Initialize driver-specific context structure */
978  state->data = NULL;
979  state->remainingBytes = 0U;
980  state->callback = userConfigPtr->callback;
981  state->callbackParam = userConfigPtr->callbackParam;
982  state->blocking = false;
983  state->driverType = userConfigPtr->driverType;
984  state->direction = userConfigPtr->direction;
985  state->status = STATUS_SUCCESS;
986  state->driverIdle = true;
987  state->bitCount = userConfigPtr->bitCount;
988 
989  if (state->direction == FLEXIO_UART_DIRECTION_TX)
990  {
991  /* Configure device for UART Tx mode */
992  FLEXIO_UART_DRV_ConfigureTx(state, userConfigPtr, inputClock);
993  }
994  else
995  {
996  /* Configure device for UART Rx mode */
997  FLEXIO_UART_DRV_ConfigureRx(state, userConfigPtr, inputClock);
998  }
999 
1000  /* Set up transfer engine */
1001  switch (state->driverType)
1002  {
1004  if (state->direction == FLEXIO_UART_DIRECTION_TX)
1005  {
1006  state->flexioCommon.isr = FLEXIO_UART_DRV_CheckStatusTx;
1007  }
1008  else
1009  {
1010  state->flexioCommon.isr = FLEXIO_UART_DRV_CheckStatusRx;
1011  }
1012  break;
1014  /* Nothing to do here, FLEXIO_UART_DRV_GetStatus() will handle the transfer */
1015  break;
1017  /* Store DMA channel number */
1018  state->dmaChannel = userConfigPtr->dmaChannel;
1019  /* Configure DMA request source */
1020  dmaReq = g_flexioDMASrc[instance][TX_SHIFTER(state->flexioCommon.resourceIndex)];
1021  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->dmaChannel, dmaReq);
1022  /* For Tx we will still need interrupt to signal end of transfer */
1023  if (state->direction == FLEXIO_UART_DIRECTION_TX)
1024  {
1025  state->flexioCommon.isr = FLEXIO_UART_DRV_CheckStatusTx;
1026  }
1027  break;
1028  default:
1029  /* Impossible type - do nothing */
1030  break;
1031  }
1032 
1033  (void)clkErr;
1034  (void)osifError;
1035  return STATUS_SUCCESS;
1036 }
1037 
1038 
1039 /*FUNCTION**********************************************************************
1040  *
1041  * Function Name : FLEXIO_UART_DRV_Deinit
1042  * Description : De-initialize the FLEXIO_UART driver
1043  * Implements : FLEXIO_UART_DRV_Deinit_Activity
1044  *
1045  *END**************************************************************************/
1047 {
1048  DEV_ASSERT(state != NULL);
1049 
1050  /* Check if driver is busy */
1051  DEV_ASSERT(state->driverIdle);
1052 
1053  /* Destroy the semaphore */
1054  if (state->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1055  {
1056  (void)OSIF_SemaDestroy(&(state->idleSemaphore));
1057  }
1058 
1059  return FLEXIO_DRV_DeinitDriver((flexio_common_state_t *)state);
1060 }
1061 
1062 
1063 /*FUNCTION**********************************************************************
1064  *
1065  * Function Name : FLEXIO_UART_DRV_SetConfig
1066  * Description : Set the baud rate and bit width for any subsequent UART transfer
1067  * Implements : FLEXIO_UART_DRV_SetConfig_Activity
1068  *
1069  *END**************************************************************************/
1071  uint32_t baudRate,
1072  uint8_t bitCount)
1073 {
1074  FLEXIO_Type *baseAddr;
1075  uint16_t divider;
1076  uint32_t inputClock;
1077  status_t clkErr;
1078  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1079 
1080  DEV_ASSERT(state != NULL);
1081  DEV_ASSERT(baudRate > 0U);
1082  DEV_ASSERT(bitCount > 0U);
1083  DEV_ASSERT(bitCount <= 16U);
1084  /* for DMA transfers bitCount must 8 */
1085  DEV_ASSERT(!((state->driverType == FLEXIO_DRIVER_TYPE_DMA) && (bitCount != 8U)));
1086 
1087  baseAddr = g_flexioBase[state->flexioCommon.instance];
1088  resourceIndex = state->flexioCommon.resourceIndex;
1089 
1090  /* Check if driver is busy */
1091  DEV_ASSERT(state->driverIdle);
1092  /* Get the protocol clock frequency */
1093  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[state->flexioCommon.instance], &inputClock);
1094  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1095  DEV_ASSERT(inputClock > 0U);
1096 
1097  /* Compute divider */
1098  FLEXIO_UART_DRV_ComputeBaudRateDivider(state, baudRate, &divider, inputClock);
1099 
1100  if (state->direction == FLEXIO_UART_DIRECTION_TX)
1101  {
1102  /* Configure tx timer */
1103  FLEXIO_SetTimerCompare(baseAddr, TX_TIMER(resourceIndex), (uint16_t)(((((uint16_t)bitCount << 1U) - 1U) << 8U) + divider));
1104  }
1105  else
1106  {
1107  /* Configure rx timer */
1108  FLEXIO_SetTimerCompare(baseAddr, RX_TIMER(resourceIndex), (uint16_t)(((((uint16_t)bitCount << 1U) - 1U) << 8U) + divider));
1109  }
1110 
1111  state->bitCount = bitCount;
1112 
1113  (void)clkErr;
1114  return STATUS_SUCCESS;
1115 }
1116 
1117 
1118 /*FUNCTION**********************************************************************
1119  *
1120  * Function Name : FLEXIO_UART_DRV_GetBaudRate
1121  * Description : Get the currently configured baud rate
1122  * Implements : FLEXIO_UART_DRV_GetBaudRate_Activity
1123  *
1124  *END**************************************************************************/
1126 {
1127  const FLEXIO_Type *baseAddr;
1128  uint32_t inputClock;
1129  uint16_t divider;
1130  uint16_t timerCmp;
1131  status_t clkErr;
1132  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1133 
1134  DEV_ASSERT(state != NULL);
1135 
1136  baseAddr = g_flexioBase[state->flexioCommon.instance];
1137  resourceIndex = state->flexioCommon.resourceIndex;
1138 
1139  /* Get the protocol clock frequency */
1140  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[state->flexioCommon.instance], &inputClock);
1141  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1142  DEV_ASSERT(inputClock > 0U);
1143 
1144  /* Get the currently configured divider */
1145  timerCmp = FLEXIO_GetTimerCompare(baseAddr, TX_TIMER(resourceIndex));
1146  divider = (uint16_t)(timerCmp & 0x00FFU);
1147 
1148  /* Compute baud rate: input_clock / (2 * (divider + 1)). Round to nearest integer */
1149  *baudRate = (inputClock + (uint32_t)divider + 1U) / (2U * ((uint32_t)divider + 1U));
1150 
1151  (void)clkErr;
1152  return STATUS_SUCCESS;
1153 }
1154 
1155 
1156 
1157 /*FUNCTION**********************************************************************
1158  *
1159  * Function Name : FLEXIO_UART_DRV_SendData
1160  * Description : Perform a non-blocking UART transmission
1161  * Implements : FLEXIO_UART_DRV_SendData_Activity
1162  *
1163  *END**************************************************************************/
1165  const uint8_t * txBuff,
1166  uint32_t txSize)
1167 {
1168  FLEXIO_Type *baseAddr;
1169  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1170 
1171  DEV_ASSERT(state != NULL);
1172  DEV_ASSERT(txBuff != NULL);
1173  DEV_ASSERT(txSize > 0U);
1174  DEV_ASSERT(state->direction == FLEXIO_UART_DIRECTION_TX);
1175 
1176  baseAddr = g_flexioBase[state->flexioCommon.instance];
1177  resourceIndex = state->flexioCommon.resourceIndex;
1178 
1179  /* Check if driver is busy */
1180  DEV_ASSERT(state->driverIdle);
1181 
1182  state->data = (uint8_t *)txBuff;
1183  state->remainingBytes = txSize;
1184  state->status = STATUS_BUSY;
1185  state->driverIdle = false;
1186  /* number of bytes to flush after the last byte is copied in the tx shifter buffer */
1187  state->txFlush = (uint8_t)((txSize == 1U) ? 1U : 2U);
1188 
1189  /* Enable timers and shifters */
1190  FLEXIO_UART_DRV_EnableTransfer(state);
1191  /* Enable transfer engine */
1192  switch (state->driverType)
1193  {
1195  /* Enable interrupts for Tx shifter */
1196  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), true);
1197  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), true);
1198  break;
1200  /* Call FLEXIO_UART_DRV_CheckStatus once to send the first byte */
1201  FLEXIO_UART_DRV_CheckStatus(state);
1202  break;
1204  FLEXIO_UART_DRV_StartTxDmaTransfer(state);
1205  break;
1206  default:
1207  /* Impossible type - do nothing */
1208  break;
1209  }
1210 
1211  return STATUS_SUCCESS;
1212 }
1213 
1214 
1215 /*FUNCTION**********************************************************************
1216  *
1217  * Function Name : FLEXIO_UART_DRV_SendDataBlocking
1218  * Description : Perform a blocking UART transmission
1219  * Implements : FLEXIO_UART_DRV_SendDataBlocking_Activity
1220  *
1221  *END**************************************************************************/
1223  const uint8_t * txBuff,
1224  uint32_t txSize,
1225  uint32_t timeout)
1226 {
1227  status_t status;
1228 
1229  /* mark transfer as blocking */
1230  if (state->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1231  {
1232  state->blocking = true;
1233  }
1234  /* Call FLEXIO_UART_DRV_SendData to start transfer */
1235  status = FLEXIO_UART_DRV_SendData(state, txBuff, txSize);
1236  if (status != STATUS_SUCCESS)
1237  {
1238  /* Transfer could not be started */
1239  state->blocking = false;
1240  return status;
1241  }
1242 
1243  /* Wait for transfer to end */
1244  return FLEXIO_UART_DRV_WaitTransferEnd(state, timeout);
1245 }
1246 
1247 
1248 /*FUNCTION**********************************************************************
1249  *
1250  * Function Name : FLEXIO_UART_DRV_ReceiveData
1251  * Description : Perform a non-blocking UART reception
1252  * Implements : FLEXIO_UART_DRV_ReceiveData_Activity
1253  *
1254  *END**************************************************************************/
1256  uint8_t * rxBuff,
1257  uint32_t rxSize)
1258 {
1259  FLEXIO_Type *baseAddr;
1260  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1261 
1262  DEV_ASSERT(state != NULL);
1263  DEV_ASSERT(rxBuff != NULL);
1264  DEV_ASSERT(rxSize > 0U);
1265  DEV_ASSERT(state->direction == FLEXIO_UART_DIRECTION_RX);
1266 
1267  baseAddr = g_flexioBase[state->flexioCommon.instance];
1268  resourceIndex = state->flexioCommon.resourceIndex;
1269 
1270  /* Check if driver is busy */
1271  DEV_ASSERT(state->driverIdle);
1272 
1273  state->data = rxBuff;
1274  state->remainingBytes = rxSize;
1275  state->status = STATUS_BUSY;
1276  state->driverIdle = false;
1277 
1278  /* Enable timers and shifters */
1279  FLEXIO_UART_DRV_EnableTransfer(state);
1280  /* Enable transfer engine */
1281  switch (state->driverType)
1282  {
1284  /* Enable interrupts for Rx shifter */
1285  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), true);
1286  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), true);
1287  break;
1289  /* Call FLEXIO_UART_DRV_CheckStatus once to send the first byte */
1290  FLEXIO_UART_DRV_CheckStatus(state);
1291  break;
1293  FLEXIO_UART_DRV_StartRxDmaTransfer(state);
1294  break;
1295  default:
1296  /* Impossible type - do nothing */
1297  break;
1298  }
1299 
1300  return STATUS_SUCCESS;
1301 }
1302 
1303 
1304 /*FUNCTION**********************************************************************
1305  *
1306  * Function Name : FLEXIO_UART_DRV_ReceiveDataBlocking
1307  * Description : Perform a blocking UART reception
1308  * Implements : FLEXIO_UART_DRV_ReceiveDataBlocking_Activity
1309  *
1310  *END**************************************************************************/
1312  uint8_t * rxBuff,
1313  uint32_t rxSize,
1314  uint32_t timeout)
1315 {
1316  status_t status;
1317 
1318  /* mark transfer as blocking */
1319  if (state->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1320  {
1321  state->blocking = true;
1322  }
1323  /* Call FLEXIO_UART_DRV_ReceiveData to start transfer */
1324  status = FLEXIO_UART_DRV_ReceiveData(state, rxBuff, rxSize);
1325  if (status != STATUS_SUCCESS)
1326  {
1327  /* Transfer could not be started */
1328  state->blocking = false;
1329  return status;
1330  }
1331 
1332  /* Wait for transfer to end */
1333  return FLEXIO_UART_DRV_WaitTransferEnd(state, timeout);
1334 }
1335 
1336 
1337 /*FUNCTION**********************************************************************
1338  *
1339  * Function Name : FLEXIO_UART_DRV_TransferAbort
1340  * Description : Aborts a non-blocking UART transfer
1341  * Implements : FLEXIO_UART_DRV_TransferAbort_Activity
1342  *
1343  *END**************************************************************************/
1345 {
1346  DEV_ASSERT(state != NULL);
1347 
1348  state->status = STATUS_UART_ABORTED;
1349  FLEXIO_UART_DRV_StopTransfer(state);
1350 
1351  return STATUS_SUCCESS;
1352 }
1353 
1354 
1355 /*FUNCTION**********************************************************************
1356  *
1357  * Function Name : FLEXIO_UART_DRV_GetStatus
1358  * Description : Get the status of the current non-blocking UART transaction
1359  * Implements : FLEXIO_UART_DRV_GetStatus_Activity
1360  *
1361  *END**************************************************************************/
1362 status_t FLEXIO_UART_DRV_GetStatus(flexio_uart_state_t *state, uint32_t *bytesRemaining)
1363 {
1364  DEV_ASSERT(state != NULL);
1365 
1366  if ((!state->driverIdle) && (state->driverType == FLEXIO_DRIVER_TYPE_POLLING))
1367  {
1368  /* In polling mode advance the UART transfer here */
1369  FLEXIO_UART_DRV_CheckStatus(state);
1370  }
1371 
1372  if (bytesRemaining != NULL)
1373  {
1374  *bytesRemaining = state->remainingBytes;
1375  }
1376 
1377  if (!state->driverIdle)
1378  {
1379  return STATUS_BUSY;
1380  }
1381  else
1382  {
1383  return state->status;
1384  }
1385 }
1386 
1387 
1388 /*FUNCTION**********************************************************************
1389  *
1390  * Function Name : FLEXIO_UART_DRV_SetRxBuffer
1391  * Description : Provide a buffer for receiving data.
1392  * Implements : FLEXIO_UART_DRV_SetRxBuffer_Activity
1393  *
1394  *END**************************************************************************/
1396  uint8_t * rxBuff,
1397  uint32_t rxSize)
1398 {
1399  DEV_ASSERT(state != NULL);
1400  DEV_ASSERT(rxBuff != NULL);
1401  DEV_ASSERT(rxSize > 0U);
1402 
1403  state->data = rxBuff;
1404  state->remainingBytes = rxSize;
1405 
1406  return STATUS_SUCCESS;
1407 }
1408 
1409 
1410 /*FUNCTION**********************************************************************
1411  *
1412  * Function Name : FLEXIO_UART_DRV_SetTxBuffer
1413  * Description : Provide a buffer for transmitting data.
1414  * Implements : FLEXIO_UART_DRV_SetTxBuffer_Activity
1415  *
1416  *END**************************************************************************/
1418  const uint8_t * txBuff,
1419  uint32_t txSize)
1420 {
1421  DEV_ASSERT(state != NULL);
1422  DEV_ASSERT(txBuff != NULL);
1423  DEV_ASSERT(txSize > 0U);
1424 
1425  state->data = (uint8_t *)txBuff;
1426  state->remainingBytes = txSize;
1427  /* in case of continuous transmission there are always 2 bytes to flush */
1428  state->txFlush = 2;
1429 
1430  return STATUS_SUCCESS;
1431 }
1432 
1433 
1434 /*******************************************************************************
1435  * EOF
1436  ******************************************************************************/
__IO uint32_t SHIFTBUF[FLEXIO_SHIFTBUF_COUNT]
Definition: S32K142.h:3405
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
status_t FLEXIO_UART_DRV_ReceiveData(flexio_uart_state_t *state, uint8_t *rxBuff, uint32_t rxSize)
Perform a non-blocking UART reception.
FLEXIO_Type *const g_flexioBase[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:56
status_t FLEXIO_UART_DRV_SetTxBuffer(flexio_uart_state_t *state, const uint8_t *txBuff, uint32_t txSize)
Provide a buffer for transmitting data.
status_t EDMA_DRV_StopChannel(uint8_t channel)
Stops the eDMA channel.
Definition: edma_driver.c:838
#define FLEXIO_INSTANCE_COUNT
Definition: S32K142.h:3421
status_t FLEXIO_UART_DRV_SetConfig(flexio_uart_state_t *state, uint32_t baudRate, uint8_t bitCount)
Set the baud rate and bit width for any subsequent UART communication.
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
status_t EDMA_DRV_SetChannelRequest(uint8_t channel, uint8_t req)
Configures the DMA request for the eDMA channel.
Definition: edma_driver.c:863
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
status_t FLEXIO_UART_DRV_SendData(flexio_uart_state_t *state, const uint8_t *txBuff, uint32_t txSize)
Perform a non-blocking UART transmission.
#define DEV_ASSERT(x)
Definition: devassert.h:77
status_t FLEXIO_UART_DRV_SendDataBlocking(flexio_uart_state_t *state, const uint8_t *txBuff, uint32_t txSize, uint32_t timeout)
Perform a blocking UART transmission.
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:193
flexio_uart_driver_direction_t direction
status_t FLEXIO_UART_DRV_ReceiveDataBlocking(flexio_uart_state_t *state, uint8_t *rxBuff, uint32_t rxSize, uint32_t timeout)
Perform a blocking UART reception.
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_driver.h:160
status_t FLEXIO_UART_DRV_GetBaudRate(flexio_uart_state_t *state, uint32_t *baudRate)
Get the currently configured baud rate.
void EDMA_DRV_SetSrcAddr(uint8_t channel, uint32_t address)
Configures the source address for the eDMA channel.
Definition: edma_driver.c:911
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
status_t FLEXIO_UART_DRV_GetStatus(flexio_uart_state_t *state, uint32_t *bytesRemaining)
Get the status of the current non-blocking UART transfer.
status_t FLEXIO_UART_DRV_SetRxBuffer(flexio_uart_state_t *state, uint8_t *rxBuff, uint32_t rxSize)
Provide a buffer for receiving data.
const uint8_t g_flexioDMASrc[FLEXIO_INSTANCE_COUNT][FEATURE_FLEXIO_MAX_SHIFTER_COUNT]
Definition: flexio_common.c:68
Driver internal context structure.
void EDMA_DRV_SetMajorLoopIterationCount(uint8_t channel, uint32_t majorLoopCount)
Configures the number of major loop iterations.
Definition: edma_driver.c:1118
status_t FLEXIO_UART_DRV_Deinit(flexio_uart_state_t *state)
De-initialize the FLEXIO_UART driver.
status_t FLEXIO_UART_DRV_TransferAbort(flexio_uart_state_t *state)
Aborts a non-blocking UART transfer.
void EDMA_DRV_SetDestAddr(uint8_t channel, uint32_t address)
Configures the destination address for the eDMA channel.
Definition: edma_driver.c:1026
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
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
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
flexio_device_state_t * g_flexioDeviceStatePtr[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:59
void(* edma_callback_t)(void *parameter, edma_chn_status_t status)
Definition for the eDMA channel callback function.
Definition: edma_driver.h:204
const clock_names_t g_flexioClock[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:65
flexio_driver_type_t driverType
Driver configuration structure.
status_t FLEXIO_UART_DRV_Init(uint32_t instance, const flexio_uart_user_config_t *userConfigPtr, flexio_uart_state_t *state)
Initialize the FLEXIO_UART driver.
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