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