S32 SDK
flexio_i2s_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_i2s_driver.h"
20 #include "flexio_hal.h"
21 #include "flexio_common.h"
22 #include "clock_manager.h"
23 
93 /*******************************************************************************
94  * Variables
95  ******************************************************************************/
96 
99  /* Constraints used for baud rate computation */
100 #define DIVIDER_MIN_VALUE 1U
101 #define DIVIDER_MAX_VALUE 0xFFU
102 
103  /* Shifters/Timers used for I2S simulation The parameter x represents the
104  resourceIndex value for the current driver instance */
105 #define TX_SHIFTER(x) (x)
106 #define RX_SHIFTER(x) (uint8_t)((x) + 1U)
107 #define SCK_TIMER(x) (x)
108 #define WS_TIMER(x) (uint8_t)((x) + 1U)
109 
110 /*******************************************************************************
111  * Private Functions
112  ******************************************************************************/
113 
114 /*FUNCTION**********************************************************************
115  *
116  * Function Name : FLEXIO_I2S_DRV_ComputeByteWidth
117  * Description : Computes the baud rate divider for a target baud rate
118  *
119  *END**************************************************************************/
120 static uint8_t FLEXIO_I2S_DRV_ComputeByteWidth(uint8_t bitsWidth)
121 {
122  uint8_t byteWidth;
123 
124  if (bitsWidth <= 8U)
125  {
126  byteWidth = 1U;
127  }
128  else if (bitsWidth <= 16U)
129  {
130  byteWidth = 2U;
131  }
132  else
133  {
134  byteWidth = 4U;
135  }
136 
137  return byteWidth;
138 }
139 
140 /*FUNCTION**********************************************************************
141  *
142  * Function Name : FLEXIO_I2S_DRV_MasterComputeBaudRateDivider
143  * Description : Computes the baud rate divider for a target baud rate
144  *
145  *END**************************************************************************/
146 static void FLEXIO_I2S_DRV_MasterComputeBaudRateDivider(flexio_i2s_master_state_t *master,
147  uint32_t baudRate,
148  uint16_t *divider,
149  uint32_t inputClock)
150 {
151  uint32_t tmpDiv;
152 
153  (void)master;
154  /* Compute divider: ((input_clock / baud_rate) / 2) - 1. Round to nearest integer */
155  tmpDiv = ((inputClock + baudRate) / (2U * baudRate)) - 1U;
156  /* Enforce upper/lower limits */
157  if (tmpDiv < DIVIDER_MIN_VALUE)
158  {
159  tmpDiv = DIVIDER_MIN_VALUE;
160  }
161  if (tmpDiv > DIVIDER_MAX_VALUE)
162  {
163  tmpDiv = DIVIDER_MAX_VALUE;
164  }
165 
166  *divider = (uint16_t)tmpDiv;
167 }
168 
169 
170 /*FUNCTION**********************************************************************
171  *
172  * Function Name : FLEXIO_I2S_DRV_MasterConfigure
173  * Description : configures the FLEXIO module as I2S master
174  *
175  *END**************************************************************************/
176 static void FLEXIO_I2S_DRV_MasterConfigure(flexio_i2s_master_state_t *master,
177  const flexio_i2s_master_user_config_t * userConfigPtr,
178  uint32_t inputClock)
179 {
180  FLEXIO_Type *baseAddr;
181  uint16_t divider;
182  uint16_t bits;
183  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
184 
185  baseAddr = g_flexioBase[master->flexioCommon.instance];
186  resourceIndex = master->flexioCommon.resourceIndex;
187 
188  /* Compute divider. */
189  FLEXIO_I2S_DRV_MasterComputeBaudRateDivider(master, userConfigPtr->baudRate, &divider, inputClock);
190  bits = userConfigPtr->bitsWidth;
191 
192  /* Configure tx shifter */
194  TX_SHIFTER(resourceIndex),
199  TX_SHIFTER(resourceIndex),
201  userConfigPtr->txPin, /* output on tx pin */
203  FLEXIO_PIN_CONFIG_DISABLED, /* disable for now, will enable on transmit */
204  SCK_TIMER(resourceIndex), /* use clock timer to drive the shifter */
206 
207  /* Configure rx shifter */
209  RX_SHIFTER(resourceIndex),
214  RX_SHIFTER(resourceIndex),
216  userConfigPtr->rxPin, /* output to rx pin */
219  SCK_TIMER(resourceIndex), /* use control timer to drive the shifter */
221 
222  /* Configure SCK timer */
223  FLEXIO_HAL_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)((((bits << 1U) - 1U) << 8U) + divider));
224  FLEXIO_HAL_SetTimerConfig(baseAddr,
225  SCK_TIMER(resourceIndex),
228  FLEXIO_TIMER_ENABLE_TRG_HIGH, /* enable when Tx data is available */
231  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
234  SCK_TIMER(resourceIndex),
235  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
238  userConfigPtr->sckPin, /* output on SCK pin */
240  FLEXIO_PIN_CONFIG_OUTPUT, /* enable output */
242 
243  /* Configure WS timer */
244 
245  FLEXIO_HAL_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bits * ((divider + 1U) * 2U)) - 1U));
246  FLEXIO_HAL_SetTimerConfig(baseAddr,
247  WS_TIMER(resourceIndex),
250  FLEXIO_TIMER_ENABLE_TIM_ENABLE, /* enable when SCK timer is enabled */
253  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
256  WS_TIMER(resourceIndex),
257  0U, /* trigger not used */
260  userConfigPtr->wsPin, /* output on WS pin */
262  FLEXIO_PIN_CONFIG_OUTPUT, /* enable output */
264 }
265 
266 
267 /*FUNCTION**********************************************************************
268  *
269  * Function Name : FLEXIO_I2S_DRV_SlaveConfigure
270  * Description : configures the FLEXIO module as I2S slave
271  *
272  *END**************************************************************************/
273 static void FLEXIO_I2S_DRV_SlaveConfigure(const flexio_i2s_slave_state_t *slave,
274  const flexio_i2s_slave_user_config_t * userConfigPtr)
275 {
276  FLEXIO_Type *baseAddr;
277  uint16_t bits;
278  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
279 
280  baseAddr = g_flexioBase[slave->flexioCommon.instance];
281  resourceIndex = slave->flexioCommon.resourceIndex;
282  bits = userConfigPtr->bitsWidth;
283 
284 
285  /* Configure tx shifter */
287  TX_SHIFTER(resourceIndex),
292  TX_SHIFTER(resourceIndex),
294  userConfigPtr->txPin, /* output on tx pin */
296  FLEXIO_PIN_CONFIG_DISABLED, /* disable for now, will enable on transmit */
297  WS_TIMER(resourceIndex), /* use clock timer to drive the shifter */
299 
300  /* Configure rx shifter */
302  RX_SHIFTER(resourceIndex),
307  RX_SHIFTER(resourceIndex),
309  userConfigPtr->rxPin, /* output to rx pin */
312  WS_TIMER(resourceIndex), /* use control timer to drive the shifter */
314 
315  /* Configure SCK timer */
316  FLEXIO_HAL_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)((bits << 2U) - 3U));
317  FLEXIO_HAL_SetTimerConfig(baseAddr,
318  SCK_TIMER(resourceIndex),
321  FLEXIO_TIMER_ENABLE_PIN_POSEDGE, /* enable on WS positive edge */
324  FLEXIO_TIMER_DECREMENT_TRG_SHIFT_TRG, /* decrement on SCK input */
327  SCK_TIMER(resourceIndex),
328  (uint8_t)(userConfigPtr->sckPin << 1U), /* trigger on SCK pin */
331  userConfigPtr->wsPin, /* use WS input pin */
335 
336  /* Configure WS timer */
337  FLEXIO_HAL_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bits << 1U) - 1U));
338  FLEXIO_HAL_SetTimerConfig(baseAddr,
339  WS_TIMER(resourceIndex),
348  WS_TIMER(resourceIndex),
349  (uint8_t)((SCK_TIMER(resourceIndex) << 2U) + 3U), /* SCK timer trigger output */
352  userConfigPtr->sckPin, /* SCK input pin */
354  FLEXIO_PIN_CONFIG_DISABLED, /* enable output */
356 }
357 
358 
359 /*FUNCTION**********************************************************************
360  *
361  * Function Name : FLEXIO_I2S_DRV_MasterEndTransfer
362  * Description : End the current transfer
363  *
364  *END**************************************************************************/
365 static void FLEXIO_I2S_DRV_MasterEndTransfer(flexio_i2s_master_state_t *master)
366 {
367  FLEXIO_Type *baseAddr;
368  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
369 
370  baseAddr = g_flexioBase[master->flexioCommon.instance];
371  resourceIndex = master->flexioCommon.resourceIndex;
372 
373  /* Disable transfer engine */
374  switch (master->driverType)
375  {
377  /* Disable interrupts for Rx and Tx shifters */
379  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
380  false);
382  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
383  false);
384  break;
386  /* Nothing to do here */
387  break;
389  /* Stop DMA channels */
390  (void)EDMA_DRV_StopChannel(master->txDMAChannel);
391  (void)EDMA_DRV_StopChannel(master->rxDMAChannel);
392  /* Disable FlexIO Tx and Rx DMA requests */
393  FLEXIO_HAL_SetShifterDMARequest(baseAddr, (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))), false);
394  break;
395  default:
396  /* Impossible type - do nothing */
397  break;
398  }
399 
400  master->driverIdle = true;
401  master->txData = NULL;
402  master->rxData = NULL;
403  master->txRemainingBytes = 0U;
404  master->rxRemainingBytes = 0U;
405 
406  /* Signal transfer end for blocking transfers */
407  if (master->blocking == true)
408  {
409  (void)OSIF_SemaPost(&(master->idleSemaphore));
410  }
411 }
412 
413 
414 /*FUNCTION**********************************************************************
415  *
416  * Function Name : FLEXIO_I2S_DRV_MasterEnableTransfer
417  * Description : Enables timers and shifters to start a transfer
418  *
419  *END**************************************************************************/
420 static void FLEXIO_I2S_DRV_MasterEnableTransfer(flexio_i2s_master_state_t *master)
421 {
422  FLEXIO_Type *baseAddr;
423  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
424 
425  resourceIndex = master->flexioCommon.resourceIndex;
426  baseAddr = g_flexioBase[master->flexioCommon.instance];
427 
428  /* enable timers and shifters */
429  FLEXIO_HAL_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_TRANSMIT);
430  FLEXIO_HAL_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_RECEIVE);
431  if (master->master)
432  {
433  FLEXIO_HAL_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_8BIT_BAUD);
434  }
435  else
436  {
437  FLEXIO_HAL_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
438  }
439  FLEXIO_HAL_SetTimerMode(baseAddr, WS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
440 }
441 
442 
443 /*FUNCTION**********************************************************************
444  *
445  * Function Name : FLEXIO_I2S_DRV_MasterStopTransfer
446  * Description : Stops the current transfer
447  *
448  *END**************************************************************************/
449 static void FLEXIO_I2S_DRV_MasterStopTransfer(flexio_i2s_master_state_t *master)
450 {
451  FLEXIO_Type *baseAddr;
452  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
453 
454  resourceIndex = master->flexioCommon.resourceIndex;
455  baseAddr = g_flexioBase[master->flexioCommon.instance];
456 
457  /* disable timers and shifters */
458  FLEXIO_HAL_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
459  FLEXIO_HAL_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
460  FLEXIO_HAL_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
461  FLEXIO_HAL_SetTimerMode(baseAddr, WS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
462  /* Disable pin output */
463  FLEXIO_HAL_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_DISABLED);
464 
465  /* clear any leftover error flags */
466  FLEXIO_HAL_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
467  FLEXIO_HAL_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
468  /* discard any leftover rx. data */
469  FLEXIO_HAL_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
470 
471  /* end the transfer */
472  FLEXIO_I2S_DRV_MasterEndTransfer(master);
473 }
474 
475 
476 /*FUNCTION**********************************************************************
477  *
478  * Function Name : FLEXIO_I2S_DRV_MasterWaitTransferEnd
479  * Description : waits for the end of a blocking transfer
480  *
481  *END**************************************************************************/
482 static status_t FLEXIO_I2S_DRV_MasterWaitTransferEnd(flexio_i2s_master_state_t *master, uint32_t timeout)
483 {
484  status_t osifError = STATUS_SUCCESS;
485 
486  switch (master->driverType)
487  {
489  /* Wait for transfer to be completed by the IRQ */
490  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
491  break;
493  /* Call FLEXIO_I2S_DRV_MasterGetStatus() to do the transfer */
494  while (FLEXIO_I2S_DRV_MasterGetStatus(master, NULL) == STATUS_BUSY) {}
495  break;
497  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
498  break;
499  default:
500  /* Impossible type - do nothing */
501  break;
502  }
503 
504  /* blocking transfer is over */
505  master->blocking = false;
506  if (osifError == STATUS_TIMEOUT)
507  {
508  /* abort current transfer */
509  master->status = STATUS_TIMEOUT;
510  FLEXIO_I2S_DRV_MasterStopTransfer(master);
511  }
512 
513  return master->status;
514 }
515 
516 
517 /*FUNCTION**********************************************************************
518  *
519  * Function Name : FLEXIO_I2S_DRV_ReadData
520  * Description : reads data received by the module
521  *
522  *END**************************************************************************/
523 static void FLEXIO_I2S_DRV_ReadData(flexio_i2s_master_state_t *master)
524 {
525  const FLEXIO_Type *baseAddr;
526  uint32_t data;
527  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
528 
529  baseAddr = g_flexioBase[master->flexioCommon.instance];
530  resourceIndex = master->flexioCommon.resourceIndex;
531 
532  /* Read data from shifter buffer */
533  data = FLEXIO_HAL_ReadShifterBuffer(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
534 
535  if (master->rxRemainingBytes > 0U)
536  {
537  if (master->rxData != NULL)
538  {
539  switch (master->byteWidth)
540  {
541  case 1U:
542  *(uint8_t *)master->rxData = (uint8_t)data;
543  break;
544  case 2U:
545  *(uint16_t *)master->rxData = (uint16_t)data;
546  break;
547  default:
548  *(uint32_t *)master->rxData = (uint32_t)data;
549  break;
550  }
551  /* Update rx buffer pointer */
552  master->rxData = &master->rxData[master->byteWidth];
553  }
554  /* Update remaining bytes count even if buffer is null */
555  master->rxRemainingBytes -= (uint32_t)(master->byteWidth);
556  }
557  else
558  {
559  /* No data to receive, just ignore the read data */
560  }
561 }
562 
563 
564 /*FUNCTION**********************************************************************
565  *
566  * Function Name : FLEXIO_I2S_DRV_WriteData
567  * Description : writes data to be transmitted by the module
568  *
569  *END**************************************************************************/
570 static void FLEXIO_I2S_DRV_WriteData(flexio_i2s_master_state_t *master)
571 {
572  FLEXIO_Type *baseAddr;
573  uint32_t data;
574  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
575 
576  baseAddr = g_flexioBase[master->flexioCommon.instance];
577  resourceIndex = master->flexioCommon.resourceIndex;
578 
579  if (master->txRemainingBytes == 0U)
580  {
581  /* Done transmitting */
582  return;
583  }
584 
585  /* Read data from user buffer and update tx buffer pointer and remaining bytes count */
586  switch (master->byteWidth)
587  {
588  case 1U:
589  data = (uint32_t)(*(const uint8_t *)master->txData);
590  break;
591  case 2U:
592  data = (uint32_t)(*(const uint16_t *)master->txData);
593  break;
594  default:
595  data = (uint32_t)(*(const uint32_t *)master->txData);
596  break;
597  }
598  master->txData = &master->txData[master->byteWidth];
599  master->txRemainingBytes -= (uint32_t)(master->byteWidth);
600 
601  /* Write data to shifter buffer */
602  /* Shift data before bit-swapping it to get the relevant bits in the lower part of the shifter */
603  data <<= 32U - (uint32_t)(master->bitsWidth);
604  FLEXIO_HAL_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), data, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
605 }
606 
607 
608 /*FUNCTION**********************************************************************
609  *
610  * Function Name : FLEXIO_I2S_DRV_MasterCheckStatus
611  * Description : Check status of the I2S transfer. This function can be
612  * called either in an interrupt routine or directly in polling
613  * mode to advance the I2S transfer.
614  *
615  *END**************************************************************************/
616 static void FLEXIO_I2S_DRV_MasterCheckStatus(void *stateStruct)
617 {
618  FLEXIO_Type *baseAddr;
619  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
621 
622  DEV_ASSERT(stateStruct != NULL);
623 
624  master = (flexio_i2s_master_state_t *)stateStruct;
625  baseAddr = g_flexioBase[master->flexioCommon.instance];
626  resourceIndex = master->flexioCommon.resourceIndex;
627 
628  /* Check for errors */
629  if (master->txData != NULL)
630  {
631  if(FLEXIO_HAL_GetShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex)))
632  {
633  master->status = STATUS_I2S_TX_UNDERRUN;
634  FLEXIO_HAL_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
635  /* Continue processing events */
636  }
637  }
638  if (master->rxData != NULL)
639  {
640  if (FLEXIO_HAL_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
641  {
642  master->status = STATUS_I2S_RX_OVERRUN;
643  FLEXIO_HAL_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
644  /* Continue processing events */
645  }
646  }
647  /* Check if data was received */
648  if (FLEXIO_HAL_GetShifterStatus(baseAddr, RX_SHIFTER(resourceIndex)))
649  {
650  FLEXIO_I2S_DRV_ReadData(master);
651  if ((master->rxData != NULL) && (master->rxRemainingBytes == 0U))
652  {
653  /* Out of rx space, call callback to allow user to provide a new buffer */
654  if (master->callback != NULL)
655  {
656  master->callback(master, FLEXIO_EVENT_RX_FULL, master->callbackParam);
657  }
658  }
659  }
660  /* Check if transmitter needs more data */
661  if (master->txData != NULL)
662  {
663  if (FLEXIO_HAL_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)))
664  {
665  FLEXIO_I2S_DRV_WriteData(master);
666  if (master->txRemainingBytes == 0U)
667  {
668  /* Out of data, call callback to allow user to provide a new buffer */
669  if (master->callback != NULL)
670  {
671  master->callback(master, FLEXIO_EVENT_TX_EMPTY, master->callbackParam);
672  }
673  if (master->txRemainingBytes == 0U)
674  {
675  /* Still no more data to transmit, transmission will stop */
676  if (master->driverType == FLEXIO_DRIVER_TYPE_INTERRUPTS)
677  {
678  /* disable tx interrupts */
679  FLEXIO_HAL_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
680  FLEXIO_HAL_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
681  /* Enable rx interrupt to signal end of transfer */
682  FLEXIO_HAL_SetShifterInterrupt(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), true);
683  }
684  master->txData = NULL;
685  }
686  }
687  }
688  }
689 
690  /* Check if transfer is over */
691  if (master->rxRemainingBytes == 0U)
692  {
693  /* Record success if there was no error */
694  if (master->status == STATUS_BUSY)
695  {
696  master->status = STATUS_SUCCESS;
697  }
698  /* End transfer */
699  FLEXIO_I2S_DRV_MasterStopTransfer(master);
700  /* Call callback to announce the event to the user */
701  if (master->callback != NULL)
702  {
703  master->callback(master, FLEXIO_EVENT_END_TRANSFER, master->callbackParam);
704  }
705  }
706 }
707 
708 
709 /*FUNCTION**********************************************************************
710  *
711  * Function Name : FLEXIO_I2S_DRV_MasterEndDmaTxTransfer
712  * Description : function called at the end of a DMA Tx transfer
713  *
714  *END**************************************************************************/
715 static void FLEXIO_I2S_DRV_MasterEndDmaTxTransfer(void *stateStruct, edma_chn_status_t status)
716 {
718  uint8_t dmaChn;
719  DMA_Type *edmaBase;
720 
721  DEV_ASSERT(stateStruct != NULL);
722 
723  (void)status;
724  master = (flexio_i2s_master_state_t *)stateStruct;
725 
726  /* Call callback to allow user to provide a new buffer */
727  if (master->callback != NULL)
728  {
729  master->callback(master, FLEXIO_EVENT_TX_EMPTY, master->callbackParam);
730  }
731  if (master->txRemainingBytes == 0U)
732  {
733  /* No more data to transmit, transmission will stop */
734  master->txData = NULL;
735  }
736  else
737  {
738  /* There is more data to transfer, restart DMA channel */
739  /* Update buffer address and size */
740  dmaChn = master->txDMAChannel;
741  edmaBase = g_edmaBase[0U];
742  EDMA_HAL_TCDSetSrcAddr(edmaBase, dmaChn, (uint32_t)(master->txData));
743  EDMA_HAL_TCDSetMajorCount(edmaBase, dmaChn, master->txRemainingBytes / master->byteWidth);
744  /* Now that this tx is set up, clear remaining bytes count */
745  master->txRemainingBytes = 0U;
746  /* Start the channel */
747  (void)EDMA_DRV_StartChannel(dmaChn);
748  }
749 }
750 
751 
752 /*FUNCTION**********************************************************************
753  *
754  * Function Name : FLEXIO_I2S_DRV_MasterEndDmaRxTransfer
755  * Description : function called at the end of a DMA Tx transfer
756  *
757  *END**************************************************************************/
758 static void FLEXIO_I2S_DRV_MasterEndDmaRxTransfer(void *stateStruct, edma_chn_status_t status)
759 {
761  uint8_t dmaChn;
762  DMA_Type *edmaBase;
763  uint32_t addr;
764 
765  DEV_ASSERT(stateStruct != NULL);
766 
767  (void)status;
768  master = (flexio_i2s_master_state_t *)stateStruct;
769 
770  /* If this was a reception, call callback to allow user to provide a new buffer */
771  if ((master->rxData != NULL) && (master->callback != NULL))
772  {
773  master->callback(master, FLEXIO_EVENT_RX_FULL, master->callbackParam);
774  }
775  if (master->rxRemainingBytes == 0U)
776  {
777  /* No more data, end transfer */
778  master->status = STATUS_SUCCESS;
779  /* End transfer */
780  FLEXIO_I2S_DRV_MasterStopTransfer(master);
781  /* Call callback to announce the event to the user */
782  if (master->callback != NULL)
783  {
784  master->callback(master, FLEXIO_EVENT_END_TRANSFER, master->callbackParam);
785  }
786  }
787  else
788  {
789  /* There is more data to transfer, restart DMA channel */
790  /* Update buffer address and size */
791  dmaChn = master->rxDMAChannel;
792  edmaBase = g_edmaBase[0U];
793  if (master->rxData != NULL)
794  {
795  addr = (uint32_t)(master->rxData);
796  }
797  else
798  {
799  /* if there is no data to receive, use dummy data as destination for DMA transfer */
800  addr = (uint32_t)(&(master->dummyDmaData));
801  }
802  EDMA_HAL_TCDSetDestAddr(edmaBase, dmaChn, addr);
803  EDMA_HAL_TCDSetMajorCount(edmaBase, dmaChn, master->rxRemainingBytes / master->byteWidth);
804  /* Now that this rx is set up, clear remaining bytes count */
805  master->rxRemainingBytes = 0U;
806  /* Start the channel */
807  (void)EDMA_DRV_StartChannel(dmaChn);
808  }
809 }
810 
811 
812 /*FUNCTION**********************************************************************
813  *
814  * Function Name : FLEXIO_I2S_DRV_MasterComputeTxRegAddr
815  * Description : Computes the address of the register used for DMA tx transfer
816  *
817  *END**************************************************************************/
818 static uint32_t FLEXIO_I2S_DRV_MasterComputeTxRegAddr(const flexio_i2s_master_state_t *master)
819 {
820  uint32_t addr;
821  const FLEXIO_Type *baseAddr;
822  uint8_t shifter;
823 
824  baseAddr = g_flexioBase[master->flexioCommon.instance];
825  shifter = TX_SHIFTER(master->flexioCommon.resourceIndex);
826  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter])) + (sizeof(uint32_t) - master->byteWidth);
827  return addr;
828 }
829 
830 
831 /*FUNCTION**********************************************************************
832  *
833  * Function Name : FLEXIO_I2S_DRV_MasterComputeRxRegAddr
834  * Description : Computes the address of the register used for DMA rx transfer
835  *
836  *END**************************************************************************/
837 static uint32_t FLEXIO_I2S_DRV_MasterComputeRxRegAddr(const flexio_i2s_master_state_t *master)
838 {
839  uint32_t addr;
840  const FLEXIO_Type *baseAddr;
841  uint8_t shifter;
842 
843  baseAddr = g_flexioBase[master->flexioCommon.instance];
844  shifter = RX_SHIFTER(master->flexioCommon.resourceIndex);
845  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter]));
846  return addr;
847 }
848 
849 
850 /*FUNCTION**********************************************************************
851  *
852  * Function Name : FLEXIO_I2S_DRV_MasterStartDmaTransfer
853  * Description : Starts a DMA transfer
854  *
855  *END**************************************************************************/
856 static void FLEXIO_I2S_DRV_MasterStartDmaTransfer(flexio_i2s_master_state_t *master)
857 {
858  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
859  DMA_Type *edmaBase = g_edmaBase[0U];
860  FLEXIO_Type *baseAddr;
861  uint32_t addr;
862  uint8_t requestMask = 0U;
863 
864  /* Table to map flexio_i2s transfer sizes to EDMA transfer sizes */
865  static const edma_transfer_size_t dmaTransferSize[4U] =
867 
868  baseAddr = g_flexioBase[master->flexioCommon.instance];
869  resourceIndex = master->flexioCommon.resourceIndex;
870 
871  /* Configure Tx channel if this is a transmission */
872  if (master->txData != NULL)
873  {
874  /* Configure the transfer control descriptor for the previously allocated channel */
875  (void)EDMA_DRV_ConfigSingleBlockTransfer(master->txDMAChannel,
877  (uint32_t)(master->txData),
878  FLEXIO_I2S_DRV_MasterComputeTxRegAddr(master),
879  dmaTransferSize[master->byteWidth - 1U],
880  master->byteWidth);
881  EDMA_HAL_TCDSetMajorCount(edmaBase, master->txDMAChannel, master->txRemainingBytes / master->byteWidth);
882  EDMA_HAL_TCDSetDisableDmaRequestAfterTCDDoneCmd(edmaBase, master->txDMAChannel, true);
883  /* Now that this tx is set up, clear remaining bytes count */
884  master->txRemainingBytes = 0U;
885 
886  /* Setup callback for DMA tx transfer end */
887  (void)EDMA_DRV_InstallCallback(master->txDMAChannel,
888  (edma_callback_t)(FLEXIO_I2S_DRV_MasterEndDmaTxTransfer),
889  (void*)(master));
890  /* Start tx DMA channel */
891  (void)EDMA_DRV_StartChannel(master->txDMAChannel);
892  requestMask = (uint8_t)(1U << TX_SHIFTER(resourceIndex));
893  }
894  /* Configure Rx channel; if this is a transmission we still use Rx for the "end transfer" event */
895  if (master->rxData != NULL)
896  {
897  addr = (uint32_t)(master->rxData);
898  }
899  else
900  {
901  /* if there is no data to receive, use dummy data as destination for DMA transfer */
902  addr = (uint32_t)(&(master->dummyDmaData));
903  }
904  /* Configure the transfer control descriptor for the previously allocated channel */
905  (void)EDMA_DRV_ConfigSingleBlockTransfer(master->rxDMAChannel,
907  FLEXIO_I2S_DRV_MasterComputeRxRegAddr(master),
908  addr,
909  dmaTransferSize[master->byteWidth - 1U],
910  master->byteWidth);
911  if (master->rxData == NULL)
912  {
913  /* if there is no data to receive, don't increment destination offset */
914  EDMA_HAL_TCDSetDestOffset(edmaBase, master->rxDMAChannel, 0);
915  }
916  EDMA_HAL_TCDSetMajorCount(edmaBase, master->rxDMAChannel, master->rxRemainingBytes / master->byteWidth);
917  EDMA_HAL_TCDSetDisableDmaRequestAfterTCDDoneCmd(edmaBase, master->rxDMAChannel, true);
918  /* Now that this rx is set up, clear remaining bytes count */
919  master->rxRemainingBytes = 0U;
920 
921  /* Setup callback for DMA rx transfer end */
922  (void)EDMA_DRV_InstallCallback(master->rxDMAChannel,
923  (edma_callback_t)(FLEXIO_I2S_DRV_MasterEndDmaRxTransfer),
924  (void*)(master));
925  /* Start rx DMA channel */
926  (void)EDMA_DRV_StartChannel(master->rxDMAChannel);
927  requestMask |= (uint8_t)(1U << RX_SHIFTER(resourceIndex));
928 
929  /* Enable FlexIO DMA requests */
930  FLEXIO_HAL_SetShifterDMARequest(baseAddr, requestMask, true);
931 }
932 
935 /*******************************************************************************
936  * Code
937  ******************************************************************************/
938 
939 /*FUNCTION**********************************************************************
940  *
941  * Function Name : FLEXIO_I2S_DRV_MasterInit
942  * Description : Initialize the FLEXIO_I2S master mode driver
943  * Implements : FLEXIO_I2S_DRV_MasterInit_Activity
944  *
945  *END**************************************************************************/
947  const flexio_i2s_master_user_config_t * userConfigPtr,
948  flexio_i2s_master_state_t * master)
949 {
950  uint32_t inputClock;
951  status_t clkErr;
952  status_t retCode;
953  status_t osifError = STATUS_SUCCESS;
954  uint8_t dmaReqTx;
955  uint8_t dmaReqRx;
956 
957  DEV_ASSERT(master != NULL);
958  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
959  /* Check that device was initialized */
960  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
961 
962  /* Get the protocol clock frequency */
963  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[instance], &inputClock);
964  DEV_ASSERT(clkErr == STATUS_SUCCESS);
965  DEV_ASSERT(inputClock > 0U);
966 
967  /* Instruct the resource allocator that we need two shifters/timers */
968  master->flexioCommon.resourceCount = 2U;
969  /* Common FlexIO driver initialization */
970  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)master);
971  if (retCode != STATUS_SUCCESS)
972  { /* Initialization failed, not enough resources */
973  return retCode;
974  }
975  /* Initialize the semaphore */
976  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
977  {
978  osifError = OSIF_SemaCreate(&(master->idleSemaphore), 0U);
979  DEV_ASSERT(osifError == STATUS_SUCCESS);
980  }
981 
982  /* Initialize driver-specific context structure */
983  master->driverType = userConfigPtr->driverType;
984  master->bitsWidth = userConfigPtr->bitsWidth;
985  master->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(userConfigPtr->bitsWidth);
986  master->driverIdle = true;
987  master->callback = userConfigPtr->callback;
988  master->callbackParam = userConfigPtr->callbackParam;
989  master->blocking = false;
990  master->txData = NULL;
991  master->txRemainingBytes = 0U;
992  master->rxData = NULL;
993  master->rxRemainingBytes = 0U;
994  master->master = true;
995  master->status = STATUS_SUCCESS;
996 
997  /* Configure device for I2S mode */
998  FLEXIO_I2S_DRV_MasterConfigure(master, userConfigPtr, inputClock);
999 
1000  /* Set up transfer engine */
1001  switch (master->driverType)
1002  {
1004  master->flexioCommon.isr = FLEXIO_I2S_DRV_MasterCheckStatus;
1005  break;
1007  /* Nothing to do here, FLEXIO_I2S_DRV_MasterGetStatus() will handle the transfer */
1008  break;
1010  /* Store DMA channel numbers */
1011  master->rxDMAChannel = userConfigPtr->rxDMAChannel;
1012  master->txDMAChannel = userConfigPtr->txDMAChannel;
1013  /* Configure DMA request sources */
1014  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(master->flexioCommon.resourceIndex)];
1015  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(master->flexioCommon.resourceIndex)];
1016  DMAMUX_HAL_SetChannelSource(g_dmamuxBase[0U], userConfigPtr->txDMAChannel, dmaReqTx);
1017  DMAMUX_HAL_SetChannelSource(g_dmamuxBase[0U], userConfigPtr->rxDMAChannel, dmaReqRx);
1018  break;
1019  default:
1020  /* Impossible type - do nothing */
1021  break;
1022  }
1023 
1024  (void)clkErr;
1025  (void)osifError;
1026  return STATUS_SUCCESS;
1027 }
1028 
1029 
1030 /*FUNCTION**********************************************************************
1031  *
1032  * Function Name : FLEXIO_I2S_DRV_MasterDeinit
1033  * Description : De-initialize the FLEXIO_I2S master mode driver
1034  * Implements : FLEXIO_I2S_DRV_MasterDeinit_Activity
1035  *
1036  *END**************************************************************************/
1038 {
1039  DEV_ASSERT(master != NULL);
1040 
1041  /* Check if driver is busy */
1042  DEV_ASSERT(master->driverIdle);
1043 
1044  /* Destroy the semaphore */
1045  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1046  {
1047  (void)OSIF_SemaDestroy(&(master->idleSemaphore));
1048  }
1049  return FLEXIO_DRV_DeinitDriver((flexio_common_state_t *)master);
1050 }
1051 
1052 
1053 /*FUNCTION**********************************************************************
1054  *
1055  * Function Name : FLEXIO_I2S_DRV_MasterSetConfig
1056  * Description : Set the baud rate and bit width for any subsequent I2S transfer
1057  * Implements : FLEXIO_I2S_DRV_MasterSetConfig_Activity
1058  *
1059  *END**************************************************************************/
1061  uint32_t baudRate,
1062  uint8_t bitsWidth)
1063 {
1064  FLEXIO_Type *baseAddr;
1065  uint16_t divider;
1066  uint32_t inputClock;
1067  status_t clkErr;
1068  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1069 
1070  DEV_ASSERT(master != NULL);
1071  DEV_ASSERT(bitsWidth <= 32U);
1072  /* for DMA transfers bitsWidth must 8, 16, or 32 */
1073  DEV_ASSERT(!((master->driverType == FLEXIO_DRIVER_TYPE_DMA) &&
1074  (bitsWidth != 8U) && (bitsWidth != 16U) && (bitsWidth != 32U)
1075  ));
1076 
1077  baseAddr = g_flexioBase[master->flexioCommon.instance];
1078  resourceIndex = master->flexioCommon.resourceIndex;
1079 
1080  /* Check if driver is busy */
1081  DEV_ASSERT(master->driverIdle);
1082  /* Get the protocol clock frequency */
1083  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1084  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1085  DEV_ASSERT(inputClock > 0U);
1086 
1087  /* Compute divider */
1088  FLEXIO_I2S_DRV_MasterComputeBaudRateDivider(master, baudRate, &divider, inputClock);
1089 
1090  /* Configure SCK timer */
1091  FLEXIO_HAL_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)(((((uint16_t)bitsWidth << 1U) - 1U) << 8U) + divider));
1092  /* Configure WS timer */
1093  FLEXIO_HAL_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bitsWidth * ((divider + 1U) * 2U)) - 1U));
1094 
1095  master->bitsWidth = bitsWidth;
1096  master->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(bitsWidth);
1097 
1098  (void)clkErr;
1099  return STATUS_SUCCESS;
1100 }
1101 
1102 
1103 /*FUNCTION**********************************************************************
1104  *
1105  * Function Name : FLEXIO_I2S_DRV_MasterGetBaudRate
1106  * Description : Get the currently configured baud rate
1107  * Implements : FLEXIO_I2S_DRV_MasterGetBaudRate_Activity
1108  *
1109  *END**************************************************************************/
1111 {
1112  const FLEXIO_Type *baseAddr;
1113  uint32_t inputClock;
1114  uint16_t divider;
1115  uint16_t timerCmp;
1116  status_t clkErr;
1117  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1118 
1119  DEV_ASSERT(master != NULL);
1120 
1121  baseAddr = g_flexioBase[master->flexioCommon.instance];
1122  resourceIndex = master->flexioCommon.resourceIndex;
1123 
1124  /* Get the protocol clock frequency */
1125  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1126  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1127  DEV_ASSERT(inputClock > 0U);
1128 
1129  /* Get the currently configured divider */
1130  timerCmp = FLEXIO_HAL_GetTimerCompare(baseAddr, SCK_TIMER(resourceIndex));
1131  divider = (uint16_t)(timerCmp & 0x00FFU);
1132 
1133  /* Compute baud rate: input_clock / (2 * (divider + 1)). Round to nearest integer */
1134  *baudRate = (inputClock + (uint32_t)divider + 1U) / (2U * ((uint32_t)divider + 1U));
1135 
1136  (void)clkErr;
1137  return STATUS_SUCCESS;
1138 }
1139 
1140 
1141 
1142 /*FUNCTION**********************************************************************
1143  *
1144  * Function Name : FLEXIO_I2S_DRV_MasterSendData
1145  * Description : Perform a non-blocking send transaction on the I2S bus
1146  * Implements : FLEXIO_I2S_DRV_MasterSendData_Activity
1147  *
1148  *END**************************************************************************/
1150  const uint8_t * txBuff,
1151  uint32_t txSize)
1152 {
1153  FLEXIO_Type *baseAddr;
1154  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1155 
1156  DEV_ASSERT(master != NULL);
1157  DEV_ASSERT(txBuff != NULL);
1158  DEV_ASSERT(txSize > 0U);
1159 
1160  baseAddr = g_flexioBase[master->flexioCommon.instance];
1161  resourceIndex = master->flexioCommon.resourceIndex;
1162 
1163  /* Check if driver is busy */
1164  DEV_ASSERT(master->driverIdle);
1165 
1166  master->txData = txBuff;
1167  master->txRemainingBytes = txSize;
1168  /* also count received data, it tells us when tx is actually completed */
1169  master->rxRemainingBytes = txSize;
1170  master->rxData = NULL;
1171  master->status = STATUS_BUSY;
1172  master->driverIdle = false;
1173 
1174  /* Enable pin output */
1175  FLEXIO_HAL_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_OUTPUT);
1176  /* Enable timers and shifters */
1177  FLEXIO_I2S_DRV_MasterEnableTransfer(master);
1178  /* Enable transfer engine */
1179  switch (master->driverType)
1180  {
1182  /* Enable interrupts for Tx shifter */
1184  (uint8_t)(1U << TX_SHIFTER(resourceIndex)),
1185  true);
1187  (uint8_t)(1U << TX_SHIFTER(resourceIndex)),
1188  true);
1189  break;
1191  /* Call FLEXIO_I2S_DRV_MasterCheckStatus once to send the first byte */
1192  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1193  break;
1195  FLEXIO_I2S_DRV_MasterStartDmaTransfer(master);
1196  break;
1197  default:
1198  /* Impossible type - do nothing */
1199  break;
1200  }
1201 
1202  return STATUS_SUCCESS;
1203 }
1204 
1205 
1206 /*FUNCTION**********************************************************************
1207  *
1208  * Function Name : FLEXIO_I2S_DRV_MasterSendDataBlocking
1209  * Description : Perform a blocking send transaction on the I2S bus
1210  * Implements : FLEXIO_I2S_DRV_MasterSendDataBlocking_Activity
1211  *
1212  *END**************************************************************************/
1214  const uint8_t * txBuff,
1215  uint32_t txSize,
1216  uint32_t timeout)
1217 {
1218  status_t status;
1219 
1220  /* mark transfer as blocking */
1221  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1222  {
1223  master->blocking = true;
1224  }
1225  /* Call FLEXIO_I2S_DRV_MasterSendData to start transfer */
1226  status = FLEXIO_I2S_DRV_MasterSendData(master, txBuff, txSize);
1227  if (status != STATUS_SUCCESS)
1228  {
1229  /* Transfer could not be started */
1230  master->blocking = false;
1231  return status;
1232  }
1233 
1234  /* Wait for transfer to end */
1235  return FLEXIO_I2S_DRV_MasterWaitTransferEnd(master, timeout);
1236 }
1237 
1238 
1239 /*FUNCTION**********************************************************************
1240  *
1241  * Function Name : FLEXIO_I2S_DRV_MasterReceiveData
1242  * Description : Perform a non-blocking receive transaction on the I2S bus
1243  * Implements : FLEXIO_I2S_DRV_MasterReceiveData_Activity
1244  *
1245  *END**************************************************************************/
1247  uint8_t * rxBuff,
1248  uint32_t rxSize)
1249 {
1250  FLEXIO_Type *baseAddr;
1251  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1252 
1253  DEV_ASSERT(master != NULL);
1254  DEV_ASSERT(rxBuff != NULL);
1255  DEV_ASSERT(rxSize > 0U);
1256 
1257  baseAddr = g_flexioBase[master->flexioCommon.instance];
1258  resourceIndex = master->flexioCommon.resourceIndex;
1259 
1260  /* Check if driver is busy */
1261  DEV_ASSERT(master->driverIdle);
1262 
1263  master->rxData = rxBuff;
1264  master->rxRemainingBytes = rxSize;
1265  master->txData = NULL;
1266  master->txRemainingBytes = 0U;
1267  master->status = STATUS_BUSY;
1268  master->driverIdle = false;
1269 
1270  /* Enable timers and shifters */
1271  FLEXIO_I2S_DRV_MasterEnableTransfer(master);
1272 
1273  /* Enable transfer engine */
1274  switch (master->driverType)
1275  {
1277  /* Enable interrupts for Rx shifter */
1279  (uint8_t)(1U << RX_SHIFTER(resourceIndex)),
1280  true);
1282  (uint8_t)(1U << RX_SHIFTER(resourceIndex)),
1283  true);
1284  break;
1286  /* Call FLEXIO_I2S_DRV_MasterCheckStatus once to send the first byte */
1287  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1288  break;
1290  FLEXIO_I2S_DRV_MasterStartDmaTransfer(master);
1291  break;
1292  default:
1293  /* Impossible type - do nothing */
1294  break;
1295  }
1296 
1297  /* For master we need to send a dummy char to start the clock.
1298  For slave just put a 0 in the buffer to keep the tx line clear while receiving. */
1299  FLEXIO_HAL_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), 0x0, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
1300 
1301  return STATUS_SUCCESS;
1302 }
1303 
1304 
1305 /*FUNCTION**********************************************************************
1306  *
1307  * Function Name : FLEXIO_I2S_DRV_MasterReceiveDataBlocking
1308  * Description : Perform a blocking receive transaction on the I2S bus
1309  * Implements : FLEXIO_I2S_DRV_MasterReceiveDataBlocking_Activity
1310  *
1311  *END**************************************************************************/
1313  uint8_t * rxBuff,
1314  uint32_t rxSize,
1315  uint32_t timeout)
1316 {
1317  status_t status;
1318 
1319  /* mark transfer as blocking */
1320  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1321  {
1322  master->blocking = true;
1323  }
1324  /* Call FLEXIO_I2S_DRV_MasterReceiveData to start transfer */
1325  status = FLEXIO_I2S_DRV_MasterReceiveData(master, rxBuff, rxSize);
1326  if (status != STATUS_SUCCESS)
1327  {
1328  /* Transfer could not be started */
1329  master->blocking = false;
1330  return status;
1331  }
1332 
1333  /* Wait for transfer to end */
1334  return FLEXIO_I2S_DRV_MasterWaitTransferEnd(master, timeout);
1335 }
1336 
1337 
1338 /*FUNCTION**********************************************************************
1339  *
1340  * Function Name : FLEXIO_I2S_DRV_MasterTransferAbort
1341  * Description : Aborts a non-blocking I2S master transaction
1342  * Implements : FLEXIO_I2S_DRV_MasterTransferAbort_Activity
1343  *
1344  *END**************************************************************************/
1346 {
1347  DEV_ASSERT(master != NULL);
1348 
1349  master->status = STATUS_I2S_ABORTED;
1350  FLEXIO_I2S_DRV_MasterStopTransfer(master);
1351 
1352  return STATUS_SUCCESS;
1353 }
1354 
1355 
1356 /*FUNCTION**********************************************************************
1357  *
1358  * Function Name : FLEXIO_I2S_DRV_MasterGetStatus
1359  * Description : Get the status of the current non-blocking I2S master transaction
1360  * Implements : FLEXIO_I2S_DRV_MasterGetStatus_Activity
1361  *
1362  *END**************************************************************************/
1364 {
1365  DEV_ASSERT(master != NULL);
1366 
1367  if ((!master->driverIdle) && (master->driverType == FLEXIO_DRIVER_TYPE_POLLING))
1368  {
1369  /* In polling mode advance the I2S transfer here */
1370  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1371  }
1372 
1373  if (bytesRemaining != NULL)
1374  {
1375  /* Use rxRemainingBytes even for transmit; byte is not transmitted
1376  until rx shifter reports a receive event */
1377  *bytesRemaining = master->rxRemainingBytes;
1378  }
1379 
1380  if (!master->driverIdle)
1381  {
1382  return STATUS_BUSY;
1383  }
1384  else
1385  {
1386  return master->status;
1387  }
1388 }
1389 
1390 
1391 /*FUNCTION**********************************************************************
1392  *
1393  * Function Name : FLEXIO_I2S_DRV_MasterSetRxBuffer
1394  * Description : Provide a buffer for receiving data.
1395  * Implements : FLEXIO_I2S_DRV_MasterSetRxBuffer_Activity
1396  *
1397  *END**************************************************************************/
1399  uint8_t * rxBuff,
1400  uint32_t rxSize)
1401 {
1402  DEV_ASSERT(master != NULL);
1403  DEV_ASSERT(rxBuff != NULL);
1404  DEV_ASSERT(rxSize > 0U);
1405 
1406  master->rxData = rxBuff;
1407  master->rxRemainingBytes = rxSize;
1408 
1409  return STATUS_SUCCESS;
1410 }
1411 
1412 
1413 /*FUNCTION**********************************************************************
1414  *
1415  * Function Name : FLEXIO_I2S_DRV_MasterSetTxBuffer
1416  * Description : Provide a buffer for transmitting data.
1417  * Implements : FLEXIO_I2S_DRV_MasterSetTxBuffer_Activity
1418  *
1419  *END**************************************************************************/
1421  const uint8_t * txBuff,
1422  uint32_t txSize)
1423 {
1424  DEV_ASSERT(master != NULL);
1425  DEV_ASSERT(txBuff != NULL);
1426  DEV_ASSERT(txSize > 0U);
1427 
1428  master->txData = txBuff;
1429  master->txRemainingBytes = txSize;
1430  /* for transmit we also count received bytes for end condition */
1431  master->rxRemainingBytes += txSize;
1432 
1433  return STATUS_SUCCESS;
1434 }
1435 
1436 
1437 /*FUNCTION**********************************************************************
1438  *
1439  * Function Name : FLEXIO_I2S_DRV_SlaveInit
1440  * Description : Initialize the FLEXIO_I2S slave mode driver
1441  * Implements : FLEXIO_I2S_DRV_SlaveInit_Activity
1442  *
1443  *END**************************************************************************/
1445  const flexio_i2s_slave_user_config_t * userConfigPtr,
1446  flexio_i2s_slave_state_t * slave)
1447 {
1448  status_t retCode;
1449  status_t osifError = STATUS_SUCCESS;
1450  uint8_t dmaReqTx;
1451  uint8_t dmaReqRx;
1452 
1453  DEV_ASSERT(slave != NULL);
1454  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
1455  /* Check that device was initialized */
1456  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
1457 
1458  /* Instruct the resource allocator that we need two shifters/timers */
1459  slave->flexioCommon.resourceCount = 2U;
1460  /* Common FlexIO driver initialization */
1461  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)slave);
1462  if (retCode != STATUS_SUCCESS)
1463  { /* Initialization failed, not enough resources */
1464  return retCode;
1465  }
1466  /* Initialize the semaphore */
1467  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1468  {
1469  osifError = OSIF_SemaCreate(&(slave->idleSemaphore), 0U);
1470  DEV_ASSERT(osifError == STATUS_SUCCESS);
1471  }
1472  /* Initialize driver-specific context structure */
1473  slave->driverType = userConfigPtr->driverType;
1474  slave->bitsWidth = userConfigPtr->bitsWidth;
1475  slave->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(userConfigPtr->bitsWidth);
1476  slave->driverIdle = true;
1477  slave->callback = userConfigPtr->callback;
1478  slave->callbackParam = userConfigPtr->callbackParam;
1479  slave->blocking = false;
1480  slave->txData = NULL;
1481  slave->txRemainingBytes = 0U;
1482  slave->rxData = NULL;
1483  slave->rxRemainingBytes = 0U;
1484  slave->master = false;
1485  slave->status = STATUS_SUCCESS;
1486 
1487  /* Configure device for I2S mode */
1488  FLEXIO_I2S_DRV_SlaveConfigure(slave, userConfigPtr);
1489 
1490  /* Set up transfer engine */
1491  switch (slave->driverType)
1492  {
1494  slave->flexioCommon.isr = FLEXIO_I2S_DRV_MasterCheckStatus;
1495  break;
1497  /* Nothing to do here, FLEXIO_I2S_DRV_MasterGetStatus() will handle the transfer */
1498  break;
1500  /* Store DMA channel numbers */
1501  slave->rxDMAChannel = userConfigPtr->rxDMAChannel;
1502  slave->txDMAChannel = userConfigPtr->txDMAChannel;
1503  /* Configure DMA request sources */
1504  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(slave->flexioCommon.resourceIndex)];
1505  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(slave->flexioCommon.resourceIndex)];
1506  DMAMUX_HAL_SetChannelSource(g_dmamuxBase[0U], userConfigPtr->txDMAChannel, dmaReqTx);
1507  DMAMUX_HAL_SetChannelSource(g_dmamuxBase[0U], userConfigPtr->rxDMAChannel, dmaReqRx);
1508  break;
1509  default:
1510  /* Impossible type - do nothing */
1511  break;
1512  }
1513 
1514  (void)osifError;
1515  return STATUS_SUCCESS;
1516 }
1517 
1518 
1519 /*FUNCTION**********************************************************************
1520  *
1521  * Function Name : FLEXIO_I2S_DRV_SlaveSetConfig
1522  * Description : Set the baud rate and bit width for any subsequent I2S transfer
1523  * Implements : FLEXIO_I2S_DRV_SlaveSetConfig_Activity
1524  *
1525  *END**************************************************************************/
1527  uint8_t bitsWidth)
1528 {
1529  FLEXIO_Type *baseAddr;
1530  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1531 
1532  DEV_ASSERT(slave != NULL);
1533  DEV_ASSERT(bitsWidth <= 32U);
1534  /* for DMA transfers bitsWidth must 8, 16, or 32 */
1535  DEV_ASSERT(!((slave->driverType == FLEXIO_DRIVER_TYPE_DMA) &&
1536  (bitsWidth != 8U) && (bitsWidth != 16U) && (bitsWidth != 32U)
1537  ));
1538 
1539  baseAddr = g_flexioBase[slave->flexioCommon.instance];
1540  resourceIndex = slave->flexioCommon.resourceIndex;
1541 
1542  /* Check if driver is busy */
1543  DEV_ASSERT(slave->driverIdle);
1544 
1545  slave->bitsWidth = bitsWidth;
1546  slave->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(bitsWidth);
1547 
1548  /* Configure SCK timer */
1549  FLEXIO_HAL_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)(((uint16_t)bitsWidth << 2U) - 3U));
1550  /* Configure WS timer */
1551  FLEXIO_HAL_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)(((uint16_t)bitsWidth << 1U) - 1U));
1552 
1553  return STATUS_SUCCESS;
1554 }
1555 
1556 
1557 /*******************************************************************************
1558  * EOF
1559  ******************************************************************************/
static void EDMA_HAL_TCDSetSrcAddr(DMA_Type *base, uint32_t channel, uint32_t address)
Configures the source address for the hardware TCD.
Definition: edma_hal.h:794
static void FLEXIO_HAL_SetShifterInterrupt(FLEXIO_Type *baseAddr, uint8_t interruptMask, bool enable)
Enables or disables the shifter interrupts.
Definition: flexio_hal.h:823
static void FLEXIO_HAL_SetShifterMode(FLEXIO_Type *baseAddr, uint8_t shifter, flexio_shifter_mode_t mode)
Sets the mode of the specified shifter.
Definition: flexio_hal.h:1198
status_t FLEXIO_I2S_DRV_MasterReceiveDataBlocking(flexio_i2s_master_state_t *master, uint8_t *rxBuff, uint32_t rxSize, uint32_t timeout)
Perform a blocking receive transaction on the I2S bus.
static uint16_t FLEXIO_HAL_GetTimerCompare(const FLEXIO_Type *baseAddr, uint8_t timer)
Returns the compare value of the specified timer.
Definition: flexio_hal.h:2091
DMAMUX_Type *const g_dmamuxBase[DMAMUX_INSTANCE_COUNT]
Array for DMAMUX module register base address.
Definition: edma_common.c:50
status_t FLEXIO_I2S_DRV_MasterReceiveData(flexio_i2s_master_state_t *master, uint8_t *rxBuff, uint32_t rxSize)
Perform a non-blocking receive transaction on the I2S bus.
static void FLEXIO_HAL_SetTimerControl(FLEXIO_Type *baseAddr, uint8_t timer, uint8_t trigger, flexio_trigger_polarity_t triggerPolarity, flexio_trigger_source_t triggerSource, uint8_t pin, flexio_pin_polarity_t pinPolarity, flexio_pin_config_t pinConfig, flexio_timer_mode_t mode)
Sets all control settings for specified timer.
Definition: flexio_hal.h:1689
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
static void FLEXIO_HAL_SetTimerMode(FLEXIO_Type *baseAddr, uint8_t timer, flexio_timer_mode_t mode)
Sets the mode of the specified timer.
Definition: flexio_hal.h:1658
status_t FLEXIO_I2S_DRV_MasterSetTxBuffer(flexio_i2s_master_state_t *master, const uint8_t *txBuff, uint32_t txSize)
Provide a buffer for transmitting data.
FLEXIO_Type *const g_flexioBase[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:56
status_t EDMA_DRV_StopChannel(uint8_t channel)
Stops the eDMA channel.
Definition: edma_driver.c:790
#define FLEXIO_INSTANCE_COUNT
Definition: S32K144.h:3507
void EDMA_HAL_TCDSetMajorCount(DMA_Type *base, uint32_t channel, uint32_t count)
Sets the major iteration count according to minor loop channel link setting.
Definition: edma_hal.c:388
status_t FLEXIO_I2S_DRV_MasterSendData(flexio_i2s_master_state_t *master, const uint8_t *txBuff, uint32_t txSize)
Perform a non-blocking send transaction on the I2S bus.
Master internal context structure.
static void FLEXIO_HAL_WriteShifterBuffer(FLEXIO_Type *baseAddr, uint8_t shifter, uint32_t value, flexio_shifter_buffer_mode_t mode)
Writes a value in the specified shifter buffer.
Definition: flexio_hal.h:1465
static void FLEXIO_HAL_SetShifterPinConfig(FLEXIO_Type *baseAddr, uint8_t shifter, flexio_pin_config_t config)
Configures the pin assigned to the specified shifter.
Definition: flexio_hal.h:1155
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
Slave configuration structure.
static void FLEXIO_HAL_SetShifterConfig(FLEXIO_Type *baseAddr, uint8_t shifter, flexio_shifter_start_t start, flexio_shifter_stop_t stop, flexio_shifter_source_t source)
Sets all configuration settings for specified shifter.
Definition: flexio_hal.h:1396
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
status_t FLEXIO_I2S_DRV_MasterDeinit(flexio_i2s_master_state_t *master)
De-initialize the FLEXIO_I2S master mode driver.
static uint32_t FLEXIO_HAL_ReadShifterBuffer(const FLEXIO_Type *baseAddr, uint8_t shifter, flexio_shifter_buffer_mode_t mode)
Reads the value from the specified shifter buffer.
Definition: flexio_hal.h:1421
status_t FLEXIO_I2S_DRV_SlaveInit(uint32_t instance, const flexio_i2s_slave_user_config_t *userConfigPtr, flexio_i2s_slave_state_t *slave)
Initialize the FLEXIO_I2S slave mode driver.
#define DEV_ASSERT(x)
Definition: devassert.h:78
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:125
static void EDMA_HAL_TCDSetDestAddr(DMA_Type *base, uint32_t channel, uint32_t address)
Configures the destination address for the TCD.
Definition: edma_hal.h:968
__IO uint32_t SHIFTBUFBIS[FLEXIO_SHIFTBUFBIS_COUNT]
Definition: S32K144.h:3493
static void FLEXIO_HAL_SetShifterControl(FLEXIO_Type *baseAddr, uint8_t shifter, flexio_shifter_mode_t mode, uint8_t pin, flexio_pin_polarity_t pinPolarity, flexio_pin_config_t pinConfig, uint8_t timer, flexio_timer_polarity_t timerPolarity)
Sets all control settings for the specified shifter.
Definition: flexio_hal.h:1228
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
status_t FLEXIO_I2S_DRV_MasterSendDataBlocking(flexio_i2s_master_state_t *master, const uint8_t *txBuff, uint32_t txSize, uint32_t timeout)
Perform a blocking send transaction on the I2S bus.
status_t FLEXIO_I2S_DRV_MasterSetConfig(flexio_i2s_master_state_t *master, uint32_t baudRate, uint8_t bitsWidth)
Set the baud rate and bit width for any subsequent I2S communication.
status_t FLEXIO_I2S_DRV_MasterGetStatus(flexio_i2s_master_state_t *master, uint32_t *bytesRemaining)
Get the status of the current non-blocking I2S master transaction.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:31
const uint8_t g_flexioDMASrc[FLEXIO_INSTANCE_COUNT][FEATURE_FLEXIO_MAX_SHIFTER_COUNT]
Definition: flexio_common.c:68
static void FLEXIO_HAL_SetTimerCompare(FLEXIO_Type *baseAddr, uint8_t timer, uint16_t value)
Configures the compare value for the specified timer.
Definition: flexio_hal.h:2118
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_hal.h:132
flexio_driver_type_t driverType
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
static void FLEXIO_HAL_SetTimerConfig(FLEXIO_Type *baseAddr, uint8_t timer, flexio_timer_start_t start, flexio_timer_stop_t stop, flexio_timer_enable_t enable, flexio_timer_disable_t disable, flexio_timer_reset_t reset, flexio_timer_decrement_t decrement, flexio_timer_output_t output)
Sets all configuration settings for specified timer.
Definition: flexio_hal.h:2060
static void EDMA_HAL_TCDSetDisableDmaRequestAfterTCDDoneCmd(DMA_Type *base, uint32_t channel, bool disable)
Disables/Enables the DMA request after the major loop completes for the TCD.
Definition: edma_hal.h:1117
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:765
status_t FLEXIO_I2S_DRV_MasterInit(uint32_t instance, const flexio_i2s_master_user_config_t *userConfigPtr, flexio_i2s_master_state_t *master)
Initialize the FLEXIO_I2S master mode driver.
static void EDMA_HAL_TCDSetDestOffset(DMA_Type *base, uint32_t channel, int16_t offset)
Configures the destination address signed offset for the TCD.
Definition: edma_hal.h:987
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
DMA_Type *const g_edmaBase[DMA_INSTANCE_COUNT]
Array for the eDMA module register base address.
Definition: edma_common.c:47
static bool FLEXIO_HAL_GetShifterStatus(const FLEXIO_Type *baseAddr, uint8_t shifter)
Returns the current status of the specified shifter.
Definition: flexio_hal.h:593
static void FLEXIO_HAL_ClearShifterErrorStatus(FLEXIO_Type *baseAddr, uint8_t shifter)
Clears the error status of the specified shifter.
Definition: flexio_hal.h:699
status_t FLEXIO_I2S_DRV_MasterSetRxBuffer(flexio_i2s_master_state_t *master, uint8_t *rxBuff, uint32_t rxSize)
Provide a buffer for receiving data.
Master configuration structure.
static void DMAMUX_HAL_SetChannelSource(DMAMUX_Type *base, uint32_t channel, uint8_t source)
Configures the DMA request for the DMAMUX channel.
Definition: dmamux_hal.h:108
static void FLEXIO_HAL_SetShifterErrorInterrupt(FLEXIO_Type *baseAddr, uint8_t interruptMask, bool enable)
Enables or disables the shifter error interrupts.
Definition: flexio_hal.h:891
void(* edma_callback_t)(void *parameter, edma_chn_status_t status)
Definition for the eDMA channel callback function.
Definition: edma_driver.h:137
static bool FLEXIO_HAL_GetShifterErrorStatus(const FLEXIO_Type *baseAddr, uint8_t shifter)
Returns the current error status of the specified shifter.
Definition: flexio_hal.h:658
status_t FLEXIO_I2S_DRV_MasterGetBaudRate(flexio_i2s_master_state_t *master, uint32_t *baudRate)
Get the currently configured baud rate.
status_t FLEXIO_I2S_DRV_MasterTransferAbort(flexio_i2s_master_state_t *master)
Aborts a non-blocking I2S master transaction.
const clock_names_t g_flexioClock[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:65
status_t EDMA_DRV_ConfigSingleBlockTransfer(uint8_t channel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t dataBufferSize)
Configures a simple single block data transfer with DMA.
Definition: edma_driver.c:487
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:285
static void FLEXIO_HAL_ClearShifterStatus(FLEXIO_Type *baseAddr, uint8_t shifter)
Clears the status of the specified shifter.
Definition: flexio_hal.h:635
static void FLEXIO_HAL_SetShifterDMARequest(FLEXIO_Type *baseAddr, uint8_t requestMask, bool enable)
Enables or disables the shifter DMA requests.
Definition: flexio_hal.h:1010
status_t FLEXIO_I2S_DRV_SlaveSetConfig(flexio_i2s_slave_state_t *slave, uint8_t bitsWidth)
Set the bit width for any subsequent I2S communication.