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_hw_access.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 */
193  FLEXIO_SetShifterConfig(baseAddr,
194  TX_SHIFTER(resourceIndex),
195  FLEXIO_SHIFTER_START_BIT_DISABLED_SH,
196  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
197  FLEXIO_SHIFTER_SOURCE_PIN);
198  FLEXIO_SetShifterControl(baseAddr,
199  TX_SHIFTER(resourceIndex),
200  FLEXIO_SHIFTER_MODE_DISABLED,
201  userConfigPtr->txPin, /* output on tx pin */
202  FLEXIO_PIN_POLARITY_HIGH,
203  FLEXIO_PIN_CONFIG_DISABLED, /* disable for now, will enable on transmit */
204  SCK_TIMER(resourceIndex), /* use clock timer to drive the shifter */
205  FLEXIO_TIMER_POLARITY_POSEDGE);
206 
207  /* Configure rx shifter */
208  FLEXIO_SetShifterConfig(baseAddr,
209  RX_SHIFTER(resourceIndex),
210  FLEXIO_SHIFTER_START_BIT_DISABLED,
211  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
212  FLEXIO_SHIFTER_SOURCE_PIN);
213  FLEXIO_SetShifterControl(baseAddr,
214  RX_SHIFTER(resourceIndex),
215  FLEXIO_SHIFTER_MODE_DISABLED,
216  userConfigPtr->rxPin, /* output to rx pin */
217  FLEXIO_PIN_POLARITY_HIGH,
218  FLEXIO_PIN_CONFIG_DISABLED,
219  SCK_TIMER(resourceIndex), /* use control timer to drive the shifter */
220  FLEXIO_TIMER_POLARITY_NEGEDGE);
221 
222  /* Configure SCK timer */
223  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)((((bits << 1U) - 1U) << 8U) + divider));
224  FLEXIO_SetTimerConfig(baseAddr,
225  SCK_TIMER(resourceIndex),
226  FLEXIO_TIMER_START_BIT_ENABLED,
227  FLEXIO_TIMER_STOP_BIT_DISABLED,
228  FLEXIO_TIMER_ENABLE_TRG_HIGH, /* enable when Tx data is available */
229  FLEXIO_TIMER_DISABLE_NEVER,
230  FLEXIO_TIMER_RESET_NEVER,
231  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
232  FLEXIO_TIMER_INITOUT_ONE);
233  FLEXIO_SetTimerControl(baseAddr,
234  SCK_TIMER(resourceIndex),
235  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
236  FLEXIO_TRIGGER_POLARITY_LOW,
237  FLEXIO_TRIGGER_SOURCE_INTERNAL,
238  userConfigPtr->sckPin, /* output on SCK pin */
239  FLEXIO_PIN_POLARITY_LOW,
240  FLEXIO_PIN_CONFIG_OUTPUT, /* enable output */
241  FLEXIO_TIMER_MODE_DISABLED);
242 
243  /* Configure WS timer */
244 
245  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bits * ((divider + 1U) * 2U)) - 1U));
246  FLEXIO_SetTimerConfig(baseAddr,
247  WS_TIMER(resourceIndex),
248  FLEXIO_TIMER_START_BIT_DISABLED,
249  FLEXIO_TIMER_STOP_BIT_DISABLED,
250  FLEXIO_TIMER_ENABLE_TIM_ENABLE, /* enable when SCK timer is enabled */
251  FLEXIO_TIMER_DISABLE_NEVER,
252  FLEXIO_TIMER_RESET_NEVER,
253  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
254  FLEXIO_TIMER_INITOUT_ONE);
255  FLEXIO_SetTimerControl(baseAddr,
256  WS_TIMER(resourceIndex),
257  0U, /* trigger not used */
258  FLEXIO_TRIGGER_POLARITY_HIGH,
259  FLEXIO_TRIGGER_SOURCE_EXTERNAL,
260  userConfigPtr->wsPin, /* output on WS pin */
261  FLEXIO_PIN_POLARITY_LOW,
262  FLEXIO_PIN_CONFIG_OUTPUT, /* enable output */
263  FLEXIO_TIMER_MODE_DISABLED);
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 */
286  FLEXIO_SetShifterConfig(baseAddr,
287  TX_SHIFTER(resourceIndex),
288  FLEXIO_SHIFTER_START_BIT_DISABLED,
289  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
290  FLEXIO_SHIFTER_SOURCE_PIN);
291  FLEXIO_SetShifterControl(baseAddr,
292  TX_SHIFTER(resourceIndex),
293  FLEXIO_SHIFTER_MODE_DISABLED,
294  userConfigPtr->txPin, /* output on tx pin */
295  FLEXIO_PIN_POLARITY_HIGH,
296  FLEXIO_PIN_CONFIG_DISABLED, /* disable for now, will enable on transmit */
297  WS_TIMER(resourceIndex), /* use clock timer to drive the shifter */
298  FLEXIO_TIMER_POLARITY_POSEDGE);
299 
300  /* Configure rx shifter */
301  FLEXIO_SetShifterConfig(baseAddr,
302  RX_SHIFTER(resourceIndex),
303  FLEXIO_SHIFTER_START_BIT_DISABLED,
304  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
305  FLEXIO_SHIFTER_SOURCE_PIN);
306  FLEXIO_SetShifterControl(baseAddr,
307  RX_SHIFTER(resourceIndex),
308  FLEXIO_SHIFTER_MODE_DISABLED,
309  userConfigPtr->rxPin, /* output to rx pin */
310  FLEXIO_PIN_POLARITY_HIGH,
311  FLEXIO_PIN_CONFIG_DISABLED,
312  WS_TIMER(resourceIndex), /* use control timer to drive the shifter */
313  FLEXIO_TIMER_POLARITY_NEGEDGE);
314 
315  /* Configure SCK timer */
316  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)((bits << 2U) - 3U));
317  FLEXIO_SetTimerConfig(baseAddr,
318  SCK_TIMER(resourceIndex),
319  FLEXIO_TIMER_START_BIT_DISABLED,
320  FLEXIO_TIMER_STOP_BIT_DISABLED,
321  FLEXIO_TIMER_ENABLE_PIN_POSEDGE, /* enable on WS positive edge */
322  FLEXIO_TIMER_DISABLE_TIM_CMP,
323  FLEXIO_TIMER_RESET_NEVER,
324  FLEXIO_TIMER_DECREMENT_TRG_SHIFT_TRG, /* decrement on SCK input */
325  FLEXIO_TIMER_INITOUT_ONE);
326  FLEXIO_SetTimerControl(baseAddr,
327  SCK_TIMER(resourceIndex),
328  (uint8_t)(userConfigPtr->sckPin << 1U), /* trigger on SCK pin */
329  FLEXIO_TRIGGER_POLARITY_LOW,
330  FLEXIO_TRIGGER_SOURCE_INTERNAL,
331  userConfigPtr->wsPin, /* use WS input pin */
332  FLEXIO_PIN_POLARITY_LOW,
333  FLEXIO_PIN_CONFIG_DISABLED,
334  FLEXIO_TIMER_MODE_DISABLED);
335 
336  /* Configure WS timer */
337  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bits << 1U) - 1U));
338  FLEXIO_SetTimerConfig(baseAddr,
339  WS_TIMER(resourceIndex),
340  FLEXIO_TIMER_START_BIT_DISABLED,
341  FLEXIO_TIMER_STOP_BIT_DISABLED,
342  FLEXIO_TIMER_ENABLE_PIN_POSEDGE_TRG_HIGH,
343  FLEXIO_TIMER_DISABLE_TIM_CMP_TRG_LOW,
344  FLEXIO_TIMER_RESET_NEVER,
345  FLEXIO_TIMER_DECREMENT_PIN_SHIFT_PIN,
346  FLEXIO_TIMER_INITOUT_ONE);
347  FLEXIO_SetTimerControl(baseAddr,
348  WS_TIMER(resourceIndex),
349  (uint8_t)((SCK_TIMER(resourceIndex) << 2U) + 3U), /* SCK timer trigger output */
350  FLEXIO_TRIGGER_POLARITY_HIGH,
351  FLEXIO_TRIGGER_SOURCE_INTERNAL,
352  userConfigPtr->sckPin, /* SCK input pin */
353  FLEXIO_PIN_POLARITY_LOW,
354  FLEXIO_PIN_CONFIG_DISABLED, /* enable output */
355  FLEXIO_TIMER_MODE_DISABLED);
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 */
378  FLEXIO_SetShifterInterrupt(baseAddr,
379  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
380  false);
381  FLEXIO_SetShifterErrorInterrupt(baseAddr,
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_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_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_TRANSMIT);
430  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_RECEIVE);
431  if (master->master)
432  {
433  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_8BIT_BAUD);
434  }
435  else
436  {
437  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
438  }
439  FLEXIO_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_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
459  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
460  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
461  FLEXIO_SetTimerMode(baseAddr, WS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
462  /* Disable pin output */
463  FLEXIO_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_DISABLED);
464 
465  /* clear any leftover error flags */
466  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
467  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
468  /* discard any leftover rx. data */
469  FLEXIO_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_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_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_GetShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex)))
632  {
633  master->status = STATUS_I2S_TX_UNDERRUN;
634  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
635  /* Continue processing events */
636  }
637  }
638  if (master->rxData != NULL)
639  {
640  if (FLEXIO_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
641  {
642  master->status = STATUS_I2S_RX_OVERRUN;
643  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
644  /* Continue processing events */
645  }
646  }
647  /* Check if data was received */
648  if (FLEXIO_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_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_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
680  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
681  /* Enable rx interrupt to signal end of transfer */
682  FLEXIO_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 
720  DEV_ASSERT(stateStruct != NULL);
721 
722  (void)status;
723  master = (flexio_i2s_master_state_t *)stateStruct;
724 
725  /* Call callback to allow user to provide a new buffer */
726  if (master->callback != NULL)
727  {
728  master->callback(master, FLEXIO_EVENT_TX_EMPTY, master->callbackParam);
729  }
730  if (master->txRemainingBytes == 0U)
731  {
732  /* No more data to transmit, transmission will stop */
733  master->txData = NULL;
734  }
735  else
736  {
737  /* There is more data to transfer, restart DMA channel */
738  /* Update buffer address and size */
739  dmaChn = master->txDMAChannel;
740  EDMA_DRV_SetSrcAddr(dmaChn, (uint32_t)(master->txData));
741  EDMA_DRV_SetMajorLoopIterationCount(dmaChn, master->txRemainingBytes / master->byteWidth);
742  /* Now that this tx is set up, clear remaining bytes count */
743  master->txRemainingBytes = 0U;
744  /* Start the channel */
745  (void)EDMA_DRV_StartChannel(dmaChn);
746  }
747 }
748 
749 
750 /*FUNCTION**********************************************************************
751  *
752  * Function Name : FLEXIO_I2S_DRV_MasterEndDmaRxTransfer
753  * Description : function called at the end of a DMA Tx transfer
754  *
755  *END**************************************************************************/
756 static void FLEXIO_I2S_DRV_MasterEndDmaRxTransfer(void *stateStruct, edma_chn_status_t status)
757 {
759  uint8_t dmaChn;
760  uint32_t addr;
761 
762  DEV_ASSERT(stateStruct != NULL);
763 
764  (void)status;
765  master = (flexio_i2s_master_state_t *)stateStruct;
766 
767  /* If this was a reception, call callback to allow user to provide a new buffer */
768  if ((master->rxData != NULL) && (master->callback != NULL))
769  {
770  master->callback(master, FLEXIO_EVENT_RX_FULL, master->callbackParam);
771  }
772  if (master->rxRemainingBytes == 0U)
773  {
774  /* No more data, end transfer */
775  master->status = STATUS_SUCCESS;
776  /* End transfer */
777  FLEXIO_I2S_DRV_MasterStopTransfer(master);
778  /* Call callback to announce the event to the user */
779  if (master->callback != NULL)
780  {
781  master->callback(master, FLEXIO_EVENT_END_TRANSFER, master->callbackParam);
782  }
783  }
784  else
785  {
786  /* There is more data to transfer, restart DMA channel */
787  /* Update buffer address and size */
788  dmaChn = master->rxDMAChannel;
789  if (master->rxData != NULL)
790  {
791  addr = (uint32_t)(master->rxData);
792  }
793  else
794  {
795  /* if there is no data to receive, use dummy data as destination for DMA transfer */
796  addr = (uint32_t)(&(master->dummyDmaData));
797  }
798  EDMA_DRV_SetDestAddr(dmaChn, addr);
799  EDMA_DRV_SetMajorLoopIterationCount(dmaChn, master->rxRemainingBytes / master->byteWidth);
800  /* Now that this rx is set up, clear remaining bytes count */
801  master->rxRemainingBytes = 0U;
802  /* Start the channel */
803  (void)EDMA_DRV_StartChannel(dmaChn);
804  }
805 }
806 
807 
808 /*FUNCTION**********************************************************************
809  *
810  * Function Name : FLEXIO_I2S_DRV_MasterComputeTxRegAddr
811  * Description : Computes the address of the register used for DMA tx transfer
812  *
813  *END**************************************************************************/
814 static uint32_t FLEXIO_I2S_DRV_MasterComputeTxRegAddr(const flexio_i2s_master_state_t *master)
815 {
816  uint32_t addr;
817  const FLEXIO_Type *baseAddr;
818  uint8_t shifter;
819 
820  baseAddr = g_flexioBase[master->flexioCommon.instance];
821  shifter = TX_SHIFTER(master->flexioCommon.resourceIndex);
822  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter])) + (sizeof(uint32_t) - master->byteWidth);
823  return addr;
824 }
825 
826 
827 /*FUNCTION**********************************************************************
828  *
829  * Function Name : FLEXIO_I2S_DRV_MasterComputeRxRegAddr
830  * Description : Computes the address of the register used for DMA rx transfer
831  *
832  *END**************************************************************************/
833 static uint32_t FLEXIO_I2S_DRV_MasterComputeRxRegAddr(const flexio_i2s_master_state_t *master)
834 {
835  uint32_t addr;
836  const FLEXIO_Type *baseAddr;
837  uint8_t shifter;
838 
839  baseAddr = g_flexioBase[master->flexioCommon.instance];
840  shifter = RX_SHIFTER(master->flexioCommon.resourceIndex);
841  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter]));
842  return addr;
843 }
844 
845 
846 /*FUNCTION**********************************************************************
847  *
848  * Function Name : FLEXIO_I2S_DRV_MasterStartDmaTransfer
849  * Description : Starts a DMA transfer
850  *
851  *END**************************************************************************/
852 static void FLEXIO_I2S_DRV_MasterStartDmaTransfer(flexio_i2s_master_state_t *master)
853 {
854  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
855  FLEXIO_Type *baseAddr;
856  uint32_t addr;
857  uint8_t requestMask = 0U;
858 
859  /* Table to map flexio_i2s transfer sizes to EDMA transfer sizes */
860  static const edma_transfer_size_t dmaTransferSize[4U] =
862 
863  baseAddr = g_flexioBase[master->flexioCommon.instance];
864  resourceIndex = master->flexioCommon.resourceIndex;
865 
866  /* Configure Tx channel if this is a transmission */
867  if (master->txData != NULL)
868  {
869  /* Configure the transfer control descriptor for the previously allocated channel */
870  (void)EDMA_DRV_ConfigMultiBlockTransfer(master->txDMAChannel,
872  (uint32_t)(master->txData),
873  FLEXIO_I2S_DRV_MasterComputeTxRegAddr(master),
874  dmaTransferSize[master->byteWidth - 1U],
875  master->byteWidth,
876  master->txRemainingBytes / master->byteWidth,
877  true);
878  /* Now that this tx is set up, clear remaining bytes count */
879  master->txRemainingBytes = 0U;
880 
881  /* Setup callback for DMA tx transfer end */
882  (void)EDMA_DRV_InstallCallback(master->txDMAChannel,
883  (edma_callback_t)(FLEXIO_I2S_DRV_MasterEndDmaTxTransfer),
884  (void*)(master));
885  /* Start tx DMA channel */
886  (void)EDMA_DRV_StartChannel(master->txDMAChannel);
887  requestMask = (uint8_t)(1U << TX_SHIFTER(resourceIndex));
888  }
889  /* Configure Rx channel; if this is a transmission we still use Rx for the "end transfer" event */
890  if (master->rxData != NULL)
891  {
892  addr = (uint32_t)(master->rxData);
893  }
894  else
895  {
896  /* if there is no data to receive, use dummy data as destination for DMA transfer */
897  addr = (uint32_t)(&(master->dummyDmaData));
898  }
899  /* Configure the transfer control descriptor for the previously allocated channel */
900  (void)EDMA_DRV_ConfigMultiBlockTransfer(master->rxDMAChannel,
902  FLEXIO_I2S_DRV_MasterComputeRxRegAddr(master),
903  addr,
904  dmaTransferSize[master->byteWidth - 1U],
905  master->byteWidth,
906  master->rxRemainingBytes / master->byteWidth,
907  true);
908  if (master->rxData == NULL)
909  {
910  /* if there is no data to receive, don't increment destination offset */
911  EDMA_DRV_SetDestOffset(master->rxDMAChannel, 0);
912  }
913  /* Now that this rx is set up, clear remaining bytes count */
914  master->rxRemainingBytes = 0U;
915 
916  /* Setup callback for DMA rx transfer end */
917  (void)EDMA_DRV_InstallCallback(master->rxDMAChannel,
918  (edma_callback_t)(FLEXIO_I2S_DRV_MasterEndDmaRxTransfer),
919  (void*)(master));
920  /* Start rx DMA channel */
921  (void)EDMA_DRV_StartChannel(master->rxDMAChannel);
922  requestMask |= (uint8_t)(1U << RX_SHIFTER(resourceIndex));
923 
924  /* Enable FlexIO DMA requests */
925  FLEXIO_SetShifterDMARequest(baseAddr, requestMask, true);
926 }
927 
930 /*******************************************************************************
931  * Code
932  ******************************************************************************/
933 
934 /*FUNCTION**********************************************************************
935  *
936  * Function Name : FLEXIO_I2S_DRV_MasterInit
937  * Description : Initialize the FLEXIO_I2S master mode driver
938  * Implements : FLEXIO_I2S_DRV_MasterInit_Activity
939  *
940  *END**************************************************************************/
942  const flexio_i2s_master_user_config_t * userConfigPtr,
943  flexio_i2s_master_state_t * master)
944 {
945  uint32_t inputClock;
946  status_t clkErr;
947  status_t retCode;
948  status_t osifError = STATUS_SUCCESS;
949  uint8_t dmaReqTx;
950  uint8_t dmaReqRx;
951 
952  DEV_ASSERT(master != NULL);
953  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
954  /* Check that device was initialized */
955  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
956 
957  /* Get the protocol clock frequency */
958  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[instance], &inputClock);
959  DEV_ASSERT(clkErr == STATUS_SUCCESS);
960  DEV_ASSERT(inputClock > 0U);
961 
962  /* Instruct the resource allocator that we need two shifters/timers */
963  master->flexioCommon.resourceCount = 2U;
964  /* Common FlexIO driver initialization */
965  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)master);
966  if (retCode != STATUS_SUCCESS)
967  { /* Initialization failed, not enough resources */
968  return retCode;
969  }
970  /* Initialize the semaphore */
971  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
972  {
973  osifError = OSIF_SemaCreate(&(master->idleSemaphore), 0U);
974  DEV_ASSERT(osifError == STATUS_SUCCESS);
975  }
976 
977  /* Initialize driver-specific context structure */
978  master->driverType = userConfigPtr->driverType;
979  master->bitsWidth = userConfigPtr->bitsWidth;
980  master->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(userConfigPtr->bitsWidth);
981  master->driverIdle = true;
982  master->callback = userConfigPtr->callback;
983  master->callbackParam = userConfigPtr->callbackParam;
984  master->blocking = false;
985  master->txData = NULL;
986  master->txRemainingBytes = 0U;
987  master->rxData = NULL;
988  master->rxRemainingBytes = 0U;
989  master->master = true;
990  master->status = STATUS_SUCCESS;
991 
992  /* Configure device for I2S mode */
993  FLEXIO_I2S_DRV_MasterConfigure(master, userConfigPtr, inputClock);
994 
995  /* Set up transfer engine */
996  switch (master->driverType)
997  {
999  master->flexioCommon.isr = FLEXIO_I2S_DRV_MasterCheckStatus;
1000  break;
1002  /* Nothing to do here, FLEXIO_I2S_DRV_MasterGetStatus() will handle the transfer */
1003  break;
1005  /* Store DMA channel numbers */
1006  master->rxDMAChannel = userConfigPtr->rxDMAChannel;
1007  master->txDMAChannel = userConfigPtr->txDMAChannel;
1008  /* Configure DMA request sources */
1009  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(master->flexioCommon.resourceIndex)];
1010  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(master->flexioCommon.resourceIndex)];
1011  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
1012  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
1013  break;
1014  default:
1015  /* Impossible type - do nothing */
1016  break;
1017  }
1018 
1019  (void)clkErr;
1020  (void)osifError;
1021  return STATUS_SUCCESS;
1022 }
1023 
1024 
1025 /*FUNCTION**********************************************************************
1026  *
1027  * Function Name : FLEXIO_I2S_DRV_MasterDeinit
1028  * Description : De-initialize the FLEXIO_I2S master mode driver
1029  * Implements : FLEXIO_I2S_DRV_MasterDeinit_Activity
1030  *
1031  *END**************************************************************************/
1033 {
1034  DEV_ASSERT(master != NULL);
1035 
1036  /* Check if driver is busy */
1037  DEV_ASSERT(master->driverIdle);
1038 
1039  /* Destroy the semaphore */
1040  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1041  {
1042  (void)OSIF_SemaDestroy(&(master->idleSemaphore));
1043  }
1044  return FLEXIO_DRV_DeinitDriver((flexio_common_state_t *)master);
1045 }
1046 
1047 
1048 /*FUNCTION**********************************************************************
1049  *
1050  * Function Name : FLEXIO_I2S_DRV_MasterSetConfig
1051  * Description : Set the baud rate and bit width for any subsequent I2S transfer
1052  * Implements : FLEXIO_I2S_DRV_MasterSetConfig_Activity
1053  *
1054  *END**************************************************************************/
1056  uint32_t baudRate,
1057  uint8_t bitsWidth)
1058 {
1059  FLEXIO_Type *baseAddr;
1060  uint16_t divider;
1061  uint32_t inputClock;
1062  status_t clkErr;
1063  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1064 
1065  DEV_ASSERT(master != NULL);
1066  DEV_ASSERT(bitsWidth <= 32U);
1067  /* for DMA transfers bitsWidth must 8, 16, or 32 */
1068  DEV_ASSERT(!((master->driverType == FLEXIO_DRIVER_TYPE_DMA) &&
1069  (bitsWidth != 8U) && (bitsWidth != 16U) && (bitsWidth != 32U)
1070  ));
1071 
1072  baseAddr = g_flexioBase[master->flexioCommon.instance];
1073  resourceIndex = master->flexioCommon.resourceIndex;
1074 
1075  /* Check if driver is busy */
1076  DEV_ASSERT(master->driverIdle);
1077  /* Get the protocol clock frequency */
1078  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1079  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1080  DEV_ASSERT(inputClock > 0U);
1081 
1082  /* Compute divider */
1083  FLEXIO_I2S_DRV_MasterComputeBaudRateDivider(master, baudRate, &divider, inputClock);
1084 
1085  /* Configure SCK timer */
1086  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)(((((uint16_t)bitsWidth << 1U) - 1U) << 8U) + divider));
1087  /* Configure WS timer */
1088  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bitsWidth * ((divider + 1U) * 2U)) - 1U));
1089 
1090  master->bitsWidth = bitsWidth;
1091  master->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(bitsWidth);
1092 
1093  (void)clkErr;
1094  return STATUS_SUCCESS;
1095 }
1096 
1097 
1098 /*FUNCTION**********************************************************************
1099  *
1100  * Function Name : FLEXIO_I2S_DRV_MasterGetBaudRate
1101  * Description : Get the currently configured baud rate
1102  * Implements : FLEXIO_I2S_DRV_MasterGetBaudRate_Activity
1103  *
1104  *END**************************************************************************/
1106 {
1107  const FLEXIO_Type *baseAddr;
1108  uint32_t inputClock;
1109  uint16_t divider;
1110  uint16_t timerCmp;
1111  status_t clkErr;
1112  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1113 
1114  DEV_ASSERT(master != NULL);
1115 
1116  baseAddr = g_flexioBase[master->flexioCommon.instance];
1117  resourceIndex = master->flexioCommon.resourceIndex;
1118 
1119  /* Get the protocol clock frequency */
1120  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1121  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1122  DEV_ASSERT(inputClock > 0U);
1123 
1124  /* Get the currently configured divider */
1125  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCK_TIMER(resourceIndex));
1126  divider = (uint16_t)(timerCmp & 0x00FFU);
1127 
1128  /* Compute baud rate: input_clock / (2 * (divider + 1)). Round to nearest integer */
1129  *baudRate = (inputClock + (uint32_t)divider + 1U) / (2U * ((uint32_t)divider + 1U));
1130 
1131  (void)clkErr;
1132  return STATUS_SUCCESS;
1133 }
1134 
1135 
1136 
1137 /*FUNCTION**********************************************************************
1138  *
1139  * Function Name : FLEXIO_I2S_DRV_MasterSendData
1140  * Description : Perform a non-blocking send transaction on the I2S bus
1141  * Implements : FLEXIO_I2S_DRV_MasterSendData_Activity
1142  *
1143  *END**************************************************************************/
1145  const uint8_t * txBuff,
1146  uint32_t txSize)
1147 {
1148  FLEXIO_Type *baseAddr;
1149  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1150 
1151  DEV_ASSERT(master != NULL);
1152  DEV_ASSERT(txBuff != NULL);
1153  DEV_ASSERT(txSize > 0U);
1154 
1155  baseAddr = g_flexioBase[master->flexioCommon.instance];
1156  resourceIndex = master->flexioCommon.resourceIndex;
1157 
1158  /* Check if driver is busy */
1159  DEV_ASSERT(master->driverIdle);
1160 
1161  master->txData = txBuff;
1162  master->txRemainingBytes = txSize;
1163  /* also count received data, it tells us when tx is actually completed */
1164  master->rxRemainingBytes = txSize;
1165  master->rxData = NULL;
1166  master->status = STATUS_BUSY;
1167  master->driverIdle = false;
1168 
1169  /* Enable pin output */
1170  FLEXIO_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_OUTPUT);
1171  /* Enable timers and shifters */
1172  FLEXIO_I2S_DRV_MasterEnableTransfer(master);
1173  /* Enable transfer engine */
1174  switch (master->driverType)
1175  {
1177  /* Enable interrupts for Tx shifter */
1178  FLEXIO_SetShifterInterrupt(baseAddr,
1179  (uint8_t)(1U << TX_SHIFTER(resourceIndex)),
1180  true);
1181  FLEXIO_SetShifterErrorInterrupt(baseAddr,
1182  (uint8_t)(1U << TX_SHIFTER(resourceIndex)),
1183  true);
1184  break;
1186  /* Call FLEXIO_I2S_DRV_MasterCheckStatus once to send the first byte */
1187  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1188  break;
1190  FLEXIO_I2S_DRV_MasterStartDmaTransfer(master);
1191  break;
1192  default:
1193  /* Impossible type - do nothing */
1194  break;
1195  }
1196 
1197  return STATUS_SUCCESS;
1198 }
1199 
1200 
1201 /*FUNCTION**********************************************************************
1202  *
1203  * Function Name : FLEXIO_I2S_DRV_MasterSendDataBlocking
1204  * Description : Perform a blocking send transaction on the I2S bus
1205  * Implements : FLEXIO_I2S_DRV_MasterSendDataBlocking_Activity
1206  *
1207  *END**************************************************************************/
1209  const uint8_t * txBuff,
1210  uint32_t txSize,
1211  uint32_t timeout)
1212 {
1213  status_t status;
1214 
1215  /* mark transfer as blocking */
1216  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1217  {
1218  master->blocking = true;
1219  }
1220  /* Call FLEXIO_I2S_DRV_MasterSendData to start transfer */
1221  status = FLEXIO_I2S_DRV_MasterSendData(master, txBuff, txSize);
1222  if (status != STATUS_SUCCESS)
1223  {
1224  /* Transfer could not be started */
1225  master->blocking = false;
1226  return status;
1227  }
1228 
1229  /* Wait for transfer to end */
1230  return FLEXIO_I2S_DRV_MasterWaitTransferEnd(master, timeout);
1231 }
1232 
1233 
1234 /*FUNCTION**********************************************************************
1235  *
1236  * Function Name : FLEXIO_I2S_DRV_MasterReceiveData
1237  * Description : Perform a non-blocking receive transaction on the I2S bus
1238  * Implements : FLEXIO_I2S_DRV_MasterReceiveData_Activity
1239  *
1240  *END**************************************************************************/
1242  uint8_t * rxBuff,
1243  uint32_t rxSize)
1244 {
1245  FLEXIO_Type *baseAddr;
1246  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1247 
1248  DEV_ASSERT(master != NULL);
1249  DEV_ASSERT(rxBuff != NULL);
1250  DEV_ASSERT(rxSize > 0U);
1251 
1252  baseAddr = g_flexioBase[master->flexioCommon.instance];
1253  resourceIndex = master->flexioCommon.resourceIndex;
1254 
1255  /* Check if driver is busy */
1256  DEV_ASSERT(master->driverIdle);
1257 
1258  master->rxData = rxBuff;
1259  master->rxRemainingBytes = rxSize;
1260  master->txData = NULL;
1261  master->txRemainingBytes = 0U;
1262  master->status = STATUS_BUSY;
1263  master->driverIdle = false;
1264 
1265  /* Enable timers and shifters */
1266  FLEXIO_I2S_DRV_MasterEnableTransfer(master);
1267 
1268  /* Enable transfer engine */
1269  switch (master->driverType)
1270  {
1272  /* Enable interrupts for Rx shifter */
1273  FLEXIO_SetShifterInterrupt(baseAddr,
1274  (uint8_t)(1U << RX_SHIFTER(resourceIndex)),
1275  true);
1276  FLEXIO_SetShifterErrorInterrupt(baseAddr,
1277  (uint8_t)(1U << RX_SHIFTER(resourceIndex)),
1278  true);
1279  break;
1281  /* Call FLEXIO_I2S_DRV_MasterCheckStatus once to send the first byte */
1282  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1283  break;
1285  FLEXIO_I2S_DRV_MasterStartDmaTransfer(master);
1286  break;
1287  default:
1288  /* Impossible type - do nothing */
1289  break;
1290  }
1291 
1292  /* For master we need to send a dummy char to start the clock.
1293  For slave just put a 0 in the buffer to keep the tx line clear while receiving. */
1294  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), 0x0, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
1295 
1296  return STATUS_SUCCESS;
1297 }
1298 
1299 
1300 /*FUNCTION**********************************************************************
1301  *
1302  * Function Name : FLEXIO_I2S_DRV_MasterReceiveDataBlocking
1303  * Description : Perform a blocking receive transaction on the I2S bus
1304  * Implements : FLEXIO_I2S_DRV_MasterReceiveDataBlocking_Activity
1305  *
1306  *END**************************************************************************/
1308  uint8_t * rxBuff,
1309  uint32_t rxSize,
1310  uint32_t timeout)
1311 {
1312  status_t status;
1313 
1314  /* mark transfer as blocking */
1315  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1316  {
1317  master->blocking = true;
1318  }
1319  /* Call FLEXIO_I2S_DRV_MasterReceiveData to start transfer */
1320  status = FLEXIO_I2S_DRV_MasterReceiveData(master, rxBuff, rxSize);
1321  if (status != STATUS_SUCCESS)
1322  {
1323  /* Transfer could not be started */
1324  master->blocking = false;
1325  return status;
1326  }
1327 
1328  /* Wait for transfer to end */
1329  return FLEXIO_I2S_DRV_MasterWaitTransferEnd(master, timeout);
1330 }
1331 
1332 
1333 /*FUNCTION**********************************************************************
1334  *
1335  * Function Name : FLEXIO_I2S_DRV_MasterTransferAbort
1336  * Description : Aborts a non-blocking I2S master transaction
1337  * Implements : FLEXIO_I2S_DRV_MasterTransferAbort_Activity
1338  *
1339  *END**************************************************************************/
1341 {
1342  DEV_ASSERT(master != NULL);
1343 
1344  master->status = STATUS_I2S_ABORTED;
1345  FLEXIO_I2S_DRV_MasterStopTransfer(master);
1346 
1347  return STATUS_SUCCESS;
1348 }
1349 
1350 
1351 /*FUNCTION**********************************************************************
1352  *
1353  * Function Name : FLEXIO_I2S_DRV_MasterGetStatus
1354  * Description : Get the status of the current non-blocking I2S master transaction
1355  * Implements : FLEXIO_I2S_DRV_MasterGetStatus_Activity
1356  *
1357  *END**************************************************************************/
1359 {
1360  DEV_ASSERT(master != NULL);
1361 
1362  if ((!master->driverIdle) && (master->driverType == FLEXIO_DRIVER_TYPE_POLLING))
1363  {
1364  /* In polling mode advance the I2S transfer here */
1365  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1366  }
1367 
1368  if (bytesRemaining != NULL)
1369  {
1370  /* Use rxRemainingBytes even for transmit; byte is not transmitted
1371  until rx shifter reports a receive event */
1372  *bytesRemaining = master->rxRemainingBytes;
1373  }
1374 
1375  if (!master->driverIdle)
1376  {
1377  return STATUS_BUSY;
1378  }
1379  else
1380  {
1381  return master->status;
1382  }
1383 }
1384 
1385 
1386 /*FUNCTION**********************************************************************
1387  *
1388  * Function Name : FLEXIO_I2S_DRV_MasterSetRxBuffer
1389  * Description : Provide a buffer for receiving data.
1390  * Implements : FLEXIO_I2S_DRV_MasterSetRxBuffer_Activity
1391  *
1392  *END**************************************************************************/
1394  uint8_t * rxBuff,
1395  uint32_t rxSize)
1396 {
1397  DEV_ASSERT(master != NULL);
1398  DEV_ASSERT(rxBuff != NULL);
1399  DEV_ASSERT(rxSize > 0U);
1400 
1401  master->rxData = rxBuff;
1402  master->rxRemainingBytes = rxSize;
1403 
1404  return STATUS_SUCCESS;
1405 }
1406 
1407 
1408 /*FUNCTION**********************************************************************
1409  *
1410  * Function Name : FLEXIO_I2S_DRV_MasterSetTxBuffer
1411  * Description : Provide a buffer for transmitting data.
1412  * Implements : FLEXIO_I2S_DRV_MasterSetTxBuffer_Activity
1413  *
1414  *END**************************************************************************/
1416  const uint8_t * txBuff,
1417  uint32_t txSize)
1418 {
1419  DEV_ASSERT(master != NULL);
1420  DEV_ASSERT(txBuff != NULL);
1421  DEV_ASSERT(txSize > 0U);
1422 
1423  master->txData = txBuff;
1424  master->txRemainingBytes = txSize;
1425  /* for transmit we also count received bytes for end condition */
1426  master->rxRemainingBytes += txSize;
1427 
1428  return STATUS_SUCCESS;
1429 }
1430 
1431 
1432 /*FUNCTION**********************************************************************
1433  *
1434  * Function Name : FLEXIO_I2S_DRV_SlaveInit
1435  * Description : Initialize the FLEXIO_I2S slave mode driver
1436  * Implements : FLEXIO_I2S_DRV_SlaveInit_Activity
1437  *
1438  *END**************************************************************************/
1440  const flexio_i2s_slave_user_config_t * userConfigPtr,
1441  flexio_i2s_slave_state_t * slave)
1442 {
1443  status_t retCode;
1444  status_t osifError = STATUS_SUCCESS;
1445  uint8_t dmaReqTx;
1446  uint8_t dmaReqRx;
1447 
1448  DEV_ASSERT(slave != NULL);
1449  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
1450  /* Check that device was initialized */
1451  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
1452 
1453  /* Instruct the resource allocator that we need two shifters/timers */
1454  slave->flexioCommon.resourceCount = 2U;
1455  /* Common FlexIO driver initialization */
1456  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)slave);
1457  if (retCode != STATUS_SUCCESS)
1458  { /* Initialization failed, not enough resources */
1459  return retCode;
1460  }
1461  /* Initialize the semaphore */
1462  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1463  {
1464  osifError = OSIF_SemaCreate(&(slave->idleSemaphore), 0U);
1465  DEV_ASSERT(osifError == STATUS_SUCCESS);
1466  }
1467  /* Initialize driver-specific context structure */
1468  slave->driverType = userConfigPtr->driverType;
1469  slave->bitsWidth = userConfigPtr->bitsWidth;
1470  slave->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(userConfigPtr->bitsWidth);
1471  slave->driverIdle = true;
1472  slave->callback = userConfigPtr->callback;
1473  slave->callbackParam = userConfigPtr->callbackParam;
1474  slave->blocking = false;
1475  slave->txData = NULL;
1476  slave->txRemainingBytes = 0U;
1477  slave->rxData = NULL;
1478  slave->rxRemainingBytes = 0U;
1479  slave->master = false;
1480  slave->status = STATUS_SUCCESS;
1481 
1482  /* Configure device for I2S mode */
1483  FLEXIO_I2S_DRV_SlaveConfigure(slave, userConfigPtr);
1484 
1485  /* Set up transfer engine */
1486  switch (slave->driverType)
1487  {
1489  slave->flexioCommon.isr = FLEXIO_I2S_DRV_MasterCheckStatus;
1490  break;
1492  /* Nothing to do here, FLEXIO_I2S_DRV_MasterGetStatus() will handle the transfer */
1493  break;
1495  /* Store DMA channel numbers */
1496  slave->rxDMAChannel = userConfigPtr->rxDMAChannel;
1497  slave->txDMAChannel = userConfigPtr->txDMAChannel;
1498  /* Configure DMA request sources */
1499  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(slave->flexioCommon.resourceIndex)];
1500  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(slave->flexioCommon.resourceIndex)];
1501  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
1502  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
1503  break;
1504  default:
1505  /* Impossible type - do nothing */
1506  break;
1507  }
1508 
1509  (void)osifError;
1510  return STATUS_SUCCESS;
1511 }
1512 
1513 
1514 /*FUNCTION**********************************************************************
1515  *
1516  * Function Name : FLEXIO_I2S_DRV_SlaveSetConfig
1517  * Description : Set the baud rate and bit width for any subsequent I2S transfer
1518  * Implements : FLEXIO_I2S_DRV_SlaveSetConfig_Activity
1519  *
1520  *END**************************************************************************/
1522  uint8_t bitsWidth)
1523 {
1524  FLEXIO_Type *baseAddr;
1525  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1526 
1527  DEV_ASSERT(slave != NULL);
1528  DEV_ASSERT(bitsWidth <= 32U);
1529  /* for DMA transfers bitsWidth must 8, 16, or 32 */
1530  DEV_ASSERT(!((slave->driverType == FLEXIO_DRIVER_TYPE_DMA) &&
1531  (bitsWidth != 8U) && (bitsWidth != 16U) && (bitsWidth != 32U)
1532  ));
1533 
1534  baseAddr = g_flexioBase[slave->flexioCommon.instance];
1535  resourceIndex = slave->flexioCommon.resourceIndex;
1536 
1537  /* Check if driver is busy */
1538  DEV_ASSERT(slave->driverIdle);
1539 
1540  slave->bitsWidth = bitsWidth;
1541  slave->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(bitsWidth);
1542 
1543  /* Configure SCK timer */
1544  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)(((uint16_t)bitsWidth << 2U) - 3U));
1545  /* Configure WS timer */
1546  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)(((uint16_t)bitsWidth << 1U) - 1U));
1547 
1548  return STATUS_SUCCESS;
1549 }
1550 
1551 
1552 /*******************************************************************************
1553  * EOF
1554  ******************************************************************************/
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.
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.
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
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:838
#define FLEXIO_INSTANCE_COUNT
Definition: S32K142.h:3421
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.
void EDMA_DRV_SetDestOffset(uint8_t channel, int16_t offset)
Configures the destination address signed offset for the eDMA channel.
Definition: edma_driver.c:1049
Master internal context structure.
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
Slave configuration structure.
status_t EDMA_DRV_SetChannelRequest(uint8_t channel, uint8_t req)
Configures the DMA request for the eDMA channel.
Definition: edma_driver.c:863
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
status_t FLEXIO_I2S_DRV_MasterDeinit(flexio_i2s_master_state_t *master)
De-initialize the FLEXIO_I2S master mode driver.
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:77
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:193
__IO uint32_t SHIFTBUFBIS[FLEXIO_SHIFTBUFBIS_COUNT]
Definition: S32K142.h:3407
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_driver.h:160
void EDMA_DRV_SetSrcAddr(uint8_t channel, uint32_t address)
Configures the source address for the eDMA channel.
Definition: edma_driver.c:911
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
status_t 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:44
const uint8_t g_flexioDMASrc[FLEXIO_INSTANCE_COUNT][FEATURE_FLEXIO_MAX_SHIFTER_COUNT]
Definition: flexio_common.c:68
void EDMA_DRV_SetMajorLoopIterationCount(uint8_t channel, uint32_t majorLoopCount)
Configures the number of major loop iterations.
Definition: edma_driver.c:1118
void EDMA_DRV_SetDestAddr(uint8_t channel, uint32_t address)
Configures the destination address for the eDMA channel.
Definition: edma_driver.c:1026
flexio_driver_type_t driverType
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
status_t EDMA_DRV_StartChannel(uint8_t channel)
Starts an eDMA channel.
Definition: edma_driver.c:813
status_t 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.
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
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.
void(* edma_callback_t)(void *parameter, edma_chn_status_t status)
Definition for the eDMA channel callback function.
Definition: edma_driver.h:204
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_ConfigMultiBlockTransfer(uint8_t channel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t blockSize, uint32_t blockCount, bool disableReqOnCompletion)
Configures a multiple block data transfer with DMA.
Definition: edma_driver.c:589
status_t EDMA_DRV_InstallCallback(uint8_t channel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:293
status_t FLEXIO_I2S_DRV_SlaveSetConfig(flexio_i2s_slave_state_t *slave, uint8_t bitsWidth)
Set the bit width for any subsequent I2S communication.