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(uint32_t baudRate,
147  uint16_t *divider,
148  uint32_t inputClock)
149 {
150  uint32_t tmpDiv;
151 
152  /* Compute divider: ((input_clock / baud_rate) / 2) - 1. Round to nearest integer */
153  tmpDiv = ((inputClock + baudRate) / (2U * baudRate)) - 1U;
154  /* Enforce upper/lower limits */
155  if (tmpDiv < DIVIDER_MIN_VALUE)
156  {
157  tmpDiv = DIVIDER_MIN_VALUE;
158  }
159  if (tmpDiv > DIVIDER_MAX_VALUE)
160  {
161  tmpDiv = DIVIDER_MAX_VALUE;
162  }
163 
164  *divider = (uint16_t)tmpDiv;
165 }
166 
167 
168 /*FUNCTION**********************************************************************
169  *
170  * Function Name : FLEXIO_I2S_DRV_MasterConfigure
171  * Description : configures the FLEXIO module as I2S master
172  *
173  *END**************************************************************************/
174 static void FLEXIO_I2S_DRV_MasterConfigure(flexio_i2s_master_state_t *master,
175  const flexio_i2s_master_user_config_t * userConfigPtr,
176  uint32_t inputClock)
177 {
178  FLEXIO_Type *baseAddr;
179  uint16_t divider;
180  uint16_t bits;
181  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
182 
183  baseAddr = g_flexioBase[master->flexioCommon.instance];
184  resourceIndex = master->flexioCommon.resourceIndex;
185 
186  /* Compute divider. */
187  FLEXIO_I2S_DRV_MasterComputeBaudRateDivider(userConfigPtr->baudRate, &divider, inputClock);
188  bits = userConfigPtr->bitsWidth;
189 
190  /* Configure tx shifter */
191  FLEXIO_SetShifterConfig(baseAddr,
192  TX_SHIFTER(resourceIndex),
193  FLEXIO_SHIFTER_START_BIT_DISABLED_SH,
194  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
195  FLEXIO_SHIFTER_SOURCE_PIN);
196  FLEXIO_SetShifterControl(baseAddr,
197  TX_SHIFTER(resourceIndex),
198  FLEXIO_SHIFTER_MODE_DISABLED,
199  userConfigPtr->txPin, /* output on tx pin */
200  FLEXIO_PIN_POLARITY_HIGH,
201  FLEXIO_PIN_CONFIG_DISABLED, /* disable for now, will enable on transmit */
202  SCK_TIMER(resourceIndex), /* use clock timer to drive the shifter */
203  FLEXIO_TIMER_POLARITY_POSEDGE);
204 
205  /* Configure rx shifter */
206  FLEXIO_SetShifterConfig(baseAddr,
207  RX_SHIFTER(resourceIndex),
208  FLEXIO_SHIFTER_START_BIT_DISABLED,
209  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
210  FLEXIO_SHIFTER_SOURCE_PIN);
211  FLEXIO_SetShifterControl(baseAddr,
212  RX_SHIFTER(resourceIndex),
213  FLEXIO_SHIFTER_MODE_DISABLED,
214  userConfigPtr->rxPin, /* output to rx pin */
215  FLEXIO_PIN_POLARITY_HIGH,
216  FLEXIO_PIN_CONFIG_DISABLED,
217  SCK_TIMER(resourceIndex), /* use control timer to drive the shifter */
218  FLEXIO_TIMER_POLARITY_NEGEDGE);
219 
220  /* Configure SCK timer */
221  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)((((bits << 1U) - 1U) << 8U) + divider));
222  FLEXIO_SetTimerConfig(baseAddr,
223  SCK_TIMER(resourceIndex),
224  FLEXIO_TIMER_START_BIT_ENABLED,
225  FLEXIO_TIMER_STOP_BIT_DISABLED,
226  FLEXIO_TIMER_ENABLE_TRG_HIGH, /* enable when Tx data is available */
227  FLEXIO_TIMER_DISABLE_NEVER,
228  FLEXIO_TIMER_RESET_NEVER,
229  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
230  FLEXIO_TIMER_INITOUT_ONE);
231  FLEXIO_SetTimerControl(baseAddr,
232  SCK_TIMER(resourceIndex),
233  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
234  FLEXIO_TRIGGER_POLARITY_LOW,
235  FLEXIO_TRIGGER_SOURCE_INTERNAL,
236  userConfigPtr->sckPin, /* output on SCK pin */
237  FLEXIO_PIN_POLARITY_LOW,
238  FLEXIO_PIN_CONFIG_OUTPUT, /* enable output */
239  FLEXIO_TIMER_MODE_DISABLED);
240 
241  /* Configure WS timer */
242 
243  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bits * ((divider + 1U) * 2U)) - 1U));
244  FLEXIO_SetTimerConfig(baseAddr,
245  WS_TIMER(resourceIndex),
246  FLEXIO_TIMER_START_BIT_DISABLED,
247  FLEXIO_TIMER_STOP_BIT_DISABLED,
248  FLEXIO_TIMER_ENABLE_TIM_ENABLE, /* enable when SCK timer is enabled */
249  FLEXIO_TIMER_DISABLE_NEVER,
250  FLEXIO_TIMER_RESET_NEVER,
251  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
252  FLEXIO_TIMER_INITOUT_ONE);
253  FLEXIO_SetTimerControl(baseAddr,
254  WS_TIMER(resourceIndex),
255  0U, /* trigger not used */
256  FLEXIO_TRIGGER_POLARITY_HIGH,
257  FLEXIO_TRIGGER_SOURCE_EXTERNAL,
258  userConfigPtr->wsPin, /* output on WS pin */
259  FLEXIO_PIN_POLARITY_LOW,
260  FLEXIO_PIN_CONFIG_OUTPUT, /* enable output */
261  FLEXIO_TIMER_MODE_DISABLED);
262 }
263 
264 
265 /*FUNCTION**********************************************************************
266  *
267  * Function Name : FLEXIO_I2S_DRV_SlaveConfigure
268  * Description : configures the FLEXIO module as I2S slave
269  *
270  *END**************************************************************************/
271 static void FLEXIO_I2S_DRV_SlaveConfigure(const flexio_i2s_slave_state_t *slave,
272  const flexio_i2s_slave_user_config_t * userConfigPtr)
273 {
274  FLEXIO_Type *baseAddr;
275  uint16_t bits;
276  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
277 
278  baseAddr = g_flexioBase[slave->flexioCommon.instance];
279  resourceIndex = slave->flexioCommon.resourceIndex;
280  bits = userConfigPtr->bitsWidth;
281 
282 
283  /* Configure tx shifter */
284  FLEXIO_SetShifterConfig(baseAddr,
285  TX_SHIFTER(resourceIndex),
286  FLEXIO_SHIFTER_START_BIT_DISABLED,
287  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
288  FLEXIO_SHIFTER_SOURCE_PIN);
289  FLEXIO_SetShifterControl(baseAddr,
290  TX_SHIFTER(resourceIndex),
291  FLEXIO_SHIFTER_MODE_DISABLED,
292  userConfigPtr->txPin, /* output on tx pin */
293  FLEXIO_PIN_POLARITY_HIGH,
294  FLEXIO_PIN_CONFIG_DISABLED, /* disable for now, will enable on transmit */
295  WS_TIMER(resourceIndex), /* use clock timer to drive the shifter */
296  FLEXIO_TIMER_POLARITY_POSEDGE);
297 
298  /* Configure rx shifter */
299  FLEXIO_SetShifterConfig(baseAddr,
300  RX_SHIFTER(resourceIndex),
301  FLEXIO_SHIFTER_START_BIT_DISABLED,
302  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
303  FLEXIO_SHIFTER_SOURCE_PIN);
304  FLEXIO_SetShifterControl(baseAddr,
305  RX_SHIFTER(resourceIndex),
306  FLEXIO_SHIFTER_MODE_DISABLED,
307  userConfigPtr->rxPin, /* output to rx pin */
308  FLEXIO_PIN_POLARITY_HIGH,
309  FLEXIO_PIN_CONFIG_DISABLED,
310  WS_TIMER(resourceIndex), /* use control timer to drive the shifter */
311  FLEXIO_TIMER_POLARITY_NEGEDGE);
312 
313  /* Configure SCK timer */
314  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)((bits << 2U) - 3U));
315  FLEXIO_SetTimerConfig(baseAddr,
316  SCK_TIMER(resourceIndex),
317  FLEXIO_TIMER_START_BIT_DISABLED,
318  FLEXIO_TIMER_STOP_BIT_DISABLED,
319  FLEXIO_TIMER_ENABLE_PIN_POSEDGE, /* enable on WS positive edge */
320  FLEXIO_TIMER_DISABLE_TIM_CMP,
321  FLEXIO_TIMER_RESET_NEVER,
322  FLEXIO_TIMER_DECREMENT_TRG_SHIFT_TRG, /* decrement on SCK input */
323  FLEXIO_TIMER_INITOUT_ONE);
324  FLEXIO_SetTimerControl(baseAddr,
325  SCK_TIMER(resourceIndex),
326  (uint8_t)(userConfigPtr->sckPin << 1U), /* trigger on SCK pin */
327  FLEXIO_TRIGGER_POLARITY_LOW,
328  FLEXIO_TRIGGER_SOURCE_INTERNAL,
329  userConfigPtr->wsPin, /* use WS input pin */
330  FLEXIO_PIN_POLARITY_LOW,
331  FLEXIO_PIN_CONFIG_DISABLED,
332  FLEXIO_TIMER_MODE_DISABLED);
333 
334  /* Configure WS timer */
335  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bits << 1U) - 1U));
336  FLEXIO_SetTimerConfig(baseAddr,
337  WS_TIMER(resourceIndex),
338  FLEXIO_TIMER_START_BIT_DISABLED,
339  FLEXIO_TIMER_STOP_BIT_DISABLED,
340  FLEXIO_TIMER_ENABLE_PIN_POSEDGE_TRG_HIGH,
341  FLEXIO_TIMER_DISABLE_TIM_CMP_TRG_LOW,
342  FLEXIO_TIMER_RESET_NEVER,
343  FLEXIO_TIMER_DECREMENT_PIN_SHIFT_PIN,
344  FLEXIO_TIMER_INITOUT_ONE);
345  FLEXIO_SetTimerControl(baseAddr,
346  WS_TIMER(resourceIndex),
347  (uint8_t)((SCK_TIMER(resourceIndex) << 2U) + 3U), /* SCK timer trigger output */
348  FLEXIO_TRIGGER_POLARITY_HIGH,
349  FLEXIO_TRIGGER_SOURCE_INTERNAL,
350  userConfigPtr->sckPin, /* SCK input pin */
351  FLEXIO_PIN_POLARITY_LOW,
352  FLEXIO_PIN_CONFIG_DISABLED, /* enable output */
353  FLEXIO_TIMER_MODE_DISABLED);
354 }
355 
356 
357 /*FUNCTION**********************************************************************
358  *
359  * Function Name : FLEXIO_I2S_DRV_MasterEndTransfer
360  * Description : End the current transfer
361  *
362  *END**************************************************************************/
363 static void FLEXIO_I2S_DRV_MasterEndTransfer(flexio_i2s_master_state_t *master)
364 {
365  FLEXIO_Type *baseAddr;
366  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
367 
368  baseAddr = g_flexioBase[master->flexioCommon.instance];
369  resourceIndex = master->flexioCommon.resourceIndex;
370 
371  /* Disable transfer engine */
372  switch (master->driverType)
373  {
375  /* Disable interrupts for Rx and Tx shifters */
376  FLEXIO_SetShifterInterrupt(baseAddr,
377  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
378  false);
379  FLEXIO_SetShifterErrorInterrupt(baseAddr,
380  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
381  false);
382  break;
384  /* Nothing to do here */
385  break;
387  /* Stop DMA channels */
388  (void)EDMA_DRV_StopChannel(master->txDMAChannel);
389  (void)EDMA_DRV_StopChannel(master->rxDMAChannel);
390  /* Disable FlexIO Tx and Rx DMA requests */
391  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))), false);
392  break;
393  default:
394  /* Impossible type - do nothing */
395  break;
396  }
397 
398  master->driverIdle = true;
399  master->txData = NULL;
400  master->rxData = NULL;
401  master->txRemainingBytes = 0U;
402  master->rxRemainingBytes = 0U;
403 
404  /* Signal transfer end for blocking transfers */
405  if (master->blocking == true)
406  {
407  (void)OSIF_SemaPost(&(master->idleSemaphore));
408  }
409 }
410 
411 
412 /*FUNCTION**********************************************************************
413  *
414  * Function Name : FLEXIO_I2S_DRV_MasterEnableTransfer
415  * Description : Enables timers and shifters to start a transfer
416  *
417  *END**************************************************************************/
418 static void FLEXIO_I2S_DRV_MasterEnableTransfer(flexio_i2s_master_state_t *master)
419 {
420  FLEXIO_Type *baseAddr;
421  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
422 
423  resourceIndex = master->flexioCommon.resourceIndex;
424  baseAddr = g_flexioBase[master->flexioCommon.instance];
425 
426  /* enable timers and shifters */
427  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_TRANSMIT);
428  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_RECEIVE);
429  if (master->master)
430  {
431  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_8BIT_BAUD);
432  }
433  else
434  {
435  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
436  }
437  FLEXIO_SetTimerMode(baseAddr, WS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
438 }
439 
440 
441 /*FUNCTION**********************************************************************
442  *
443  * Function Name : FLEXIO_I2S_DRV_MasterStopTransfer
444  * Description : Stops the current transfer
445  *
446  *END**************************************************************************/
447 static void FLEXIO_I2S_DRV_MasterStopTransfer(flexio_i2s_master_state_t *master)
448 {
449  FLEXIO_Type *baseAddr;
450  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
451 
452  resourceIndex = master->flexioCommon.resourceIndex;
453  baseAddr = g_flexioBase[master->flexioCommon.instance];
454 
455  /* disable timers and shifters */
456  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
457  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
458  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
459  FLEXIO_SetTimerMode(baseAddr, WS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
460  /* Disable pin output */
461  FLEXIO_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_DISABLED);
462 
463  /* clear any leftover error flags */
464  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
465  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
466  /* discard any leftover rx. data */
467  FLEXIO_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
468 
469  /* end the transfer */
470  FLEXIO_I2S_DRV_MasterEndTransfer(master);
471 }
472 
473 
474 /*FUNCTION**********************************************************************
475  *
476  * Function Name : FLEXIO_I2S_DRV_MasterWaitTransferEnd
477  * Description : waits for the end of a blocking transfer
478  *
479  *END**************************************************************************/
480 static status_t FLEXIO_I2S_DRV_MasterWaitTransferEnd(flexio_i2s_master_state_t *master, uint32_t timeout)
481 {
482  status_t osifError = STATUS_SUCCESS;
483 
484  switch (master->driverType)
485  {
487  /* Wait for transfer to be completed by the IRQ */
488  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
489  break;
491  /* Call FLEXIO_I2S_DRV_MasterGetStatus() to do the transfer */
492  while (FLEXIO_I2S_DRV_MasterGetStatus(master, NULL) == STATUS_BUSY) {}
493  break;
495  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
496  break;
497  default:
498  /* Impossible type - do nothing */
499  break;
500  }
501 
502  /* blocking transfer is over */
503  master->blocking = false;
504  if (osifError == STATUS_TIMEOUT)
505  {
506  /* abort current transfer */
507  master->status = STATUS_TIMEOUT;
508  FLEXIO_I2S_DRV_MasterStopTransfer(master);
509  }
510 
511  return master->status;
512 }
513 
514 
515 /*FUNCTION**********************************************************************
516  *
517  * Function Name : FLEXIO_I2S_DRV_ReadData
518  * Description : reads data received by the module
519  *
520  *END**************************************************************************/
521 static void FLEXIO_I2S_DRV_ReadData(flexio_i2s_master_state_t *master)
522 {
523  const FLEXIO_Type *baseAddr;
524  uint32_t data;
525  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
526 
527  baseAddr = g_flexioBase[master->flexioCommon.instance];
528  resourceIndex = master->flexioCommon.resourceIndex;
529 
530  /* Read data from shifter buffer */
531  data = FLEXIO_ReadShifterBuffer(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
532 
533  if (master->rxRemainingBytes > 0U)
534  {
535  if (master->rxData != NULL)
536  {
537  switch (master->byteWidth)
538  {
539  case 1U:
540  *(uint8_t *)master->rxData = (uint8_t)data;
541  break;
542  case 2U:
543  *(uint16_t *)master->rxData = (uint16_t)data;
544  break;
545  default:
546  *(uint32_t *)master->rxData = (uint32_t)data;
547  break;
548  }
549  /* Update rx buffer pointer */
550  master->rxData = &master->rxData[master->byteWidth];
551  }
552  /* Update remaining bytes count even if buffer is null */
553  master->rxRemainingBytes -= (uint32_t)(master->byteWidth);
554  }
555  else
556  {
557  /* No data to receive, just ignore the read data */
558  }
559 }
560 
561 
562 /*FUNCTION**********************************************************************
563  *
564  * Function Name : FLEXIO_I2S_DRV_WriteData
565  * Description : writes data to be transmitted by the module
566  *
567  *END**************************************************************************/
568 static void FLEXIO_I2S_DRV_WriteData(flexio_i2s_master_state_t *master)
569 {
570  FLEXIO_Type *baseAddr;
571  uint32_t data;
572  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
573 
574  baseAddr = g_flexioBase[master->flexioCommon.instance];
575  resourceIndex = master->flexioCommon.resourceIndex;
576 
577  if (master->txRemainingBytes == 0U)
578  {
579  /* Done transmitting */
580  return;
581  }
582 
583  /* Read data from user buffer and update tx buffer pointer and remaining bytes count */
584  switch (master->byteWidth)
585  {
586  case 1U:
587  data = (uint32_t)(*(const uint8_t *)master->txData);
588  break;
589  case 2U:
590  data = (uint32_t)(*(const uint16_t *)master->txData);
591  break;
592  default:
593  data = (uint32_t)(*(const uint32_t *)master->txData);
594  break;
595  }
596  master->txData = &master->txData[master->byteWidth];
597  master->txRemainingBytes -= (uint32_t)(master->byteWidth);
598 
599  /* Write data to shifter buffer */
600  /* Shift data before bit-swapping it to get the relevant bits in the lower part of the shifter */
601  data <<= 32U - (uint32_t)(master->bitsWidth);
602  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), data, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
603 }
604 
605 
606 /*FUNCTION**********************************************************************
607  *
608  * Function Name : FLEXIO_I2S_DRV_MasterCheckStatus
609  * Description : Check status of the I2S transfer. This function can be
610  * called either in an interrupt routine or directly in polling
611  * mode to advance the I2S transfer.
612  *
613  *END**************************************************************************/
614 static void FLEXIO_I2S_DRV_MasterCheckStatus(void *stateStruct)
615 {
616  FLEXIO_Type *baseAddr;
617  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
619 
620  DEV_ASSERT(stateStruct != NULL);
621 
622  master = (flexio_i2s_master_state_t *)stateStruct;
623  baseAddr = g_flexioBase[master->flexioCommon.instance];
624  resourceIndex = master->flexioCommon.resourceIndex;
625 
626  /* Check for errors */
627  if (master->txData != NULL)
628  {
629  if(FLEXIO_GetShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex)))
630  {
631  master->status = STATUS_I2S_TX_UNDERRUN;
632  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
633  /* Continue processing events */
634  }
635  }
636  if (master->rxData != NULL)
637  {
638  if (FLEXIO_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
639  {
640  master->status = STATUS_I2S_RX_OVERRUN;
641  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
642  /* Continue processing events */
643  }
644  }
645  /* Check if data was received */
646  if (FLEXIO_GetShifterStatus(baseAddr, RX_SHIFTER(resourceIndex)))
647  {
648  FLEXIO_I2S_DRV_ReadData(master);
649  if ((master->rxData != NULL) && (master->rxRemainingBytes == 0U))
650  {
651  /* Out of rx space, call callback to allow user to provide a new buffer */
652  if (master->callback != NULL)
653  {
654  master->callback(I2S_EVENT_RX_FULL, master->callbackParam);
655  }
656  }
657  }
658  /* Check if transmitter needs more data */
659  if (master->txData != NULL)
660  {
661  if (FLEXIO_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)))
662  {
663  FLEXIO_I2S_DRV_WriteData(master);
664  if (master->txRemainingBytes == 0U)
665  {
666  /* Out of data, call callback to allow user to provide a new buffer */
667  if (master->callback != NULL)
668  {
669  master->callback(I2S_EVENT_TX_EMPTY, master->callbackParam);
670  }
671  if (master->txRemainingBytes == 0U)
672  {
673  /* Still no more data to transmit, transmission will stop */
674  if (master->driverType == FLEXIO_DRIVER_TYPE_INTERRUPTS)
675  {
676  /* disable tx interrupts */
677  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
678  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
679  /* Enable rx interrupt to signal end of transfer */
680  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), true);
681  }
682  master->txData = NULL;
683  }
684  }
685  }
686  }
687 
688  /* Check if transfer is over */
689  if (master->rxRemainingBytes == 0U)
690  {
691  /* Record success if there was no error */
692  if (master->status == STATUS_BUSY)
693  {
694  master->status = STATUS_SUCCESS;
695  }
696  /* End transfer */
697  FLEXIO_I2S_DRV_MasterStopTransfer(master);
698  /* Call callback to announce the event to the user */
699  if (master->callback != NULL)
700  {
701  master->callback(I2S_EVENT_END_TRANSFER, master->callbackParam);
702  }
703  }
704 }
705 
706 
707 /*FUNCTION**********************************************************************
708  *
709  * Function Name : FLEXIO_I2S_DRV_MasterEndDmaTxTransfer
710  * Description : function called at the end of a DMA Tx transfer
711  *
712  *END**************************************************************************/
713 static void FLEXIO_I2S_DRV_MasterEndDmaTxTransfer(void *stateStruct, edma_chn_status_t status)
714 {
716  uint8_t dmaChn;
717 
718  DEV_ASSERT(stateStruct != NULL);
719 
720  (void)status;
721  master = (flexio_i2s_master_state_t *)stateStruct;
722 
723  /* Call callback to allow user to provide a new buffer */
724  if (master->callback != NULL)
725  {
726  master->callback(I2S_EVENT_TX_EMPTY, master->callbackParam);
727  }
728  if (master->txRemainingBytes == 0U)
729  {
730  /* No more data to transmit, transmission will stop */
731  master->txData = NULL;
732  }
733  else
734  {
735  /* There is more data to transfer, restart DMA channel */
736  /* Update buffer address and size */
737  dmaChn = master->txDMAChannel;
738  EDMA_DRV_SetSrcAddr(dmaChn, (uint32_t)(master->txData));
739  EDMA_DRV_SetMajorLoopIterationCount(dmaChn, master->txRemainingBytes / master->byteWidth);
740  /* Now that this tx is set up, clear remaining bytes count */
741  master->txRemainingBytes = 0U;
742  /* Start the channel */
743  (void)EDMA_DRV_StartChannel(dmaChn);
744  }
745 }
746 
747 
748 /*FUNCTION**********************************************************************
749  *
750  * Function Name : FLEXIO_I2S_DRV_MasterEndDmaRxTransfer
751  * Description : function called at the end of a DMA Tx transfer
752  *
753  *END**************************************************************************/
754 static void FLEXIO_I2S_DRV_MasterEndDmaRxTransfer(void *stateStruct, edma_chn_status_t status)
755 {
757  uint8_t dmaChn;
758  uint32_t addr;
759 
760  DEV_ASSERT(stateStruct != NULL);
761 
762  (void)status;
763  master = (flexio_i2s_master_state_t *)stateStruct;
764 
765  /* If this was a reception, call callback to allow user to provide a new buffer */
766  if ((master->rxData != NULL) && (master->callback != NULL))
767  {
768  master->callback(I2S_EVENT_RX_FULL, master->callbackParam);
769  }
770  if (master->rxRemainingBytes == 0U)
771  {
772  /* No more data, end transfer */
773  master->status = STATUS_SUCCESS;
774  /* End transfer */
775  FLEXIO_I2S_DRV_MasterStopTransfer(master);
776  /* Call callback to announce the event to the user */
777  if (master->callback != NULL)
778  {
779  master->callback(I2S_EVENT_END_TRANSFER, master->callbackParam);
780  }
781  }
782  else
783  {
784  /* There is more data to transfer, restart DMA channel */
785  /* Update buffer address and size */
786  dmaChn = master->rxDMAChannel;
787  if (master->rxData != NULL)
788  {
789  addr = (uint32_t)(master->rxData);
790  }
791  else
792  {
793  /* if there is no data to receive, use dummy data as destination for DMA transfer */
794  addr = (uint32_t)(&(master->dummyDmaData));
795  }
796  EDMA_DRV_SetDestAddr(dmaChn, addr);
797  EDMA_DRV_SetMajorLoopIterationCount(dmaChn, master->rxRemainingBytes / master->byteWidth);
798  /* Now that this rx is set up, clear remaining bytes count */
799  master->rxRemainingBytes = 0U;
800  /* Start the channel */
801  (void)EDMA_DRV_StartChannel(dmaChn);
802  }
803 }
804 
805 
806 /*FUNCTION**********************************************************************
807  *
808  * Function Name : FLEXIO_I2S_DRV_MasterComputeTxRegAddr
809  * Description : Computes the address of the register used for DMA tx transfer
810  *
811  *END**************************************************************************/
812 static uint32_t FLEXIO_I2S_DRV_MasterComputeTxRegAddr(const flexio_i2s_master_state_t *master)
813 {
814  uint32_t addr;
815  const FLEXIO_Type *baseAddr;
816  uint8_t shifter;
817 
818  baseAddr = g_flexioBase[master->flexioCommon.instance];
819  shifter = TX_SHIFTER(master->flexioCommon.resourceIndex);
820  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter])) + (sizeof(uint32_t) - master->byteWidth);
821  return addr;
822 }
823 
824 
825 /*FUNCTION**********************************************************************
826  *
827  * Function Name : FLEXIO_I2S_DRV_MasterComputeRxRegAddr
828  * Description : Computes the address of the register used for DMA rx transfer
829  *
830  *END**************************************************************************/
831 static uint32_t FLEXIO_I2S_DRV_MasterComputeRxRegAddr(const flexio_i2s_master_state_t *master)
832 {
833  uint32_t addr;
834  const FLEXIO_Type *baseAddr;
835  uint8_t shifter;
836 
837  baseAddr = g_flexioBase[master->flexioCommon.instance];
838  shifter = RX_SHIFTER(master->flexioCommon.resourceIndex);
839  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter]));
840  return addr;
841 }
842 
843 
844 /*FUNCTION**********************************************************************
845  *
846  * Function Name : FLEXIO_I2S_DRV_MasterStartDmaTransfer
847  * Description : Starts a DMA transfer
848  *
849  *END**************************************************************************/
850 static void FLEXIO_I2S_DRV_MasterStartDmaTransfer(flexio_i2s_master_state_t *master)
851 {
852  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
853  FLEXIO_Type *baseAddr;
854  uint32_t addr;
855  uint8_t requestMask = 0U;
856 
857  /* Table to map flexio_i2s transfer sizes to EDMA transfer sizes */
858  static const edma_transfer_size_t dmaTransferSize[4U] =
860 
861  baseAddr = g_flexioBase[master->flexioCommon.instance];
862  resourceIndex = master->flexioCommon.resourceIndex;
863 
864  /* Configure Tx channel if this is a transmission */
865  if (master->txData != NULL)
866  {
867  /* Configure the transfer control descriptor for the previously allocated channel */
868  (void)EDMA_DRV_ConfigMultiBlockTransfer(master->txDMAChannel,
870  (uint32_t)(master->txData),
871  FLEXIO_I2S_DRV_MasterComputeTxRegAddr(master),
872  dmaTransferSize[master->byteWidth - 1U],
873  master->byteWidth,
874  master->txRemainingBytes / master->byteWidth,
875  true);
876  /* Now that this tx is set up, clear remaining bytes count */
877  master->txRemainingBytes = 0U;
878 
879  /* Setup callback for DMA tx transfer end */
880  (void)EDMA_DRV_InstallCallback(master->txDMAChannel,
881  (edma_callback_t)(FLEXIO_I2S_DRV_MasterEndDmaTxTransfer),
882  (void*)(master));
883  /* Start tx DMA channel */
884  (void)EDMA_DRV_StartChannel(master->txDMAChannel);
885  requestMask = (uint8_t)(1U << TX_SHIFTER(resourceIndex));
886  }
887  /* Configure Rx channel; if this is a transmission we still use Rx for the "end transfer" event */
888  if (master->rxData != NULL)
889  {
890  addr = (uint32_t)(master->rxData);
891  }
892  else
893  {
894  /* if there is no data to receive, use dummy data as destination for DMA transfer */
895  addr = (uint32_t)(&(master->dummyDmaData));
896  }
897  /* Configure the transfer control descriptor for the previously allocated channel */
898  (void)EDMA_DRV_ConfigMultiBlockTransfer(master->rxDMAChannel,
900  FLEXIO_I2S_DRV_MasterComputeRxRegAddr(master),
901  addr,
902  dmaTransferSize[master->byteWidth - 1U],
903  master->byteWidth,
904  master->rxRemainingBytes / master->byteWidth,
905  true);
906  if (master->rxData == NULL)
907  {
908  /* if there is no data to receive, don't increment destination offset */
909  EDMA_DRV_SetDestOffset(master->rxDMAChannel, 0);
910  }
911  /* Now that this rx is set up, clear remaining bytes count */
912  master->rxRemainingBytes = 0U;
913 
914  /* Setup callback for DMA rx transfer end */
915  (void)EDMA_DRV_InstallCallback(master->rxDMAChannel,
916  (edma_callback_t)(FLEXIO_I2S_DRV_MasterEndDmaRxTransfer),
917  (void*)(master));
918  /* Start rx DMA channel */
919  (void)EDMA_DRV_StartChannel(master->rxDMAChannel);
920  requestMask |= (uint8_t)(1U << RX_SHIFTER(resourceIndex));
921 
922  /* Enable FlexIO DMA requests */
923  FLEXIO_SetShifterDMARequest(baseAddr, requestMask, true);
924 }
925 
928 /*******************************************************************************
929  * Code
930  ******************************************************************************/
931 
932 /*FUNCTION**********************************************************************
933  *
934  * Function Name : FLEXIO_I2S_DRV_MasterInit
935  * Description : Initialize the FLEXIO_I2S master mode driver
936  * Implements : FLEXIO_I2S_DRV_MasterInit_Activity
937  *
938  *END**************************************************************************/
940  const flexio_i2s_master_user_config_t * userConfigPtr,
941  flexio_i2s_master_state_t * master)
942 {
943  uint32_t inputClock;
944  status_t clkErr;
945  status_t retCode;
946  status_t osifError = STATUS_SUCCESS;
947  uint8_t dmaReqTx;
948  uint8_t dmaReqRx;
949 
950  DEV_ASSERT(master != NULL);
951  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
952  /* Check that device was initialized */
953  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
954 
955  /* Get the protocol clock frequency */
956  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[instance], &inputClock);
957  DEV_ASSERT(clkErr == STATUS_SUCCESS);
958  DEV_ASSERT(inputClock > 0U);
959 
960  /* Instruct the resource allocator that we need two shifters/timers */
961  master->flexioCommon.resourceCount = 2U;
962  /* Common FlexIO driver initialization */
963  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)master);
964  if (retCode != STATUS_SUCCESS)
965  { /* Initialization failed, not enough resources */
966  return retCode;
967  }
968  /* Initialize the semaphore */
969  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
970  {
971  osifError = OSIF_SemaCreate(&(master->idleSemaphore), 0U);
972  DEV_ASSERT(osifError == STATUS_SUCCESS);
973  }
974 
975  /* Initialize driver-specific context structure */
976  master->driverType = userConfigPtr->driverType;
977  master->bitsWidth = userConfigPtr->bitsWidth;
978  master->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(userConfigPtr->bitsWidth);
979  master->driverIdle = true;
980  master->callback = userConfigPtr->callback;
981  master->callbackParam = userConfigPtr->callbackParam;
982  master->blocking = false;
983  master->txData = NULL;
984  master->txRemainingBytes = 0U;
985  master->rxData = NULL;
986  master->rxRemainingBytes = 0U;
987  master->master = true;
988  master->status = STATUS_SUCCESS;
989 
990  /* Configure device for I2S mode */
991  FLEXIO_I2S_DRV_MasterConfigure(master, userConfigPtr, inputClock);
992 
993  /* Set up transfer engine */
994  switch (master->driverType)
995  {
997  master->flexioCommon.isr = FLEXIO_I2S_DRV_MasterCheckStatus;
998  break;
1000  /* Nothing to do here, FLEXIO_I2S_DRV_MasterGetStatus() will handle the transfer */
1001  break;
1003  /* Store DMA channel numbers */
1004  master->rxDMAChannel = userConfigPtr->rxDMAChannel;
1005  master->txDMAChannel = userConfigPtr->txDMAChannel;
1006  /* Configure DMA request sources */
1007  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(master->flexioCommon.resourceIndex)];
1008  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(master->flexioCommon.resourceIndex)];
1009  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
1010  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
1011  break;
1012  default:
1013  /* Impossible type - do nothing */
1014  break;
1015  }
1016 
1017  (void)clkErr;
1018  (void)osifError;
1019  return STATUS_SUCCESS;
1020 }
1021 
1022 
1023 /*FUNCTION**********************************************************************
1024  *
1025  * Function Name : FLEXIO_I2S_DRV_MasterDeinit
1026  * Description : De-initialize the FLEXIO_I2S master mode driver
1027  * Implements : FLEXIO_I2S_DRV_MasterDeinit_Activity
1028  *
1029  *END**************************************************************************/
1031 {
1032  DEV_ASSERT(master != NULL);
1033 
1034  /* Check if driver is busy */
1035  DEV_ASSERT(master->driverIdle);
1036 
1037  /* Destroy the semaphore */
1038  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1039  {
1040  (void)OSIF_SemaDestroy(&(master->idleSemaphore));
1041  }
1042  return FLEXIO_DRV_DeinitDriver((flexio_common_state_t *)master);
1043 }
1044 
1045 
1046 /*FUNCTION**********************************************************************
1047  *
1048  * Function Name : FLEXIO_I2S_DRV_MasterSetConfig
1049  * Description : Set the baud rate and bit width for any subsequent I2S transfer
1050  * Implements : FLEXIO_I2S_DRV_MasterSetConfig_Activity
1051  *
1052  *END**************************************************************************/
1054  uint32_t baudRate,
1055  uint8_t bitsWidth)
1056 {
1057  FLEXIO_Type *baseAddr;
1058  uint16_t divider;
1059  uint32_t inputClock;
1060  status_t clkErr;
1061  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1062 
1063  DEV_ASSERT(master != NULL);
1064  DEV_ASSERT(bitsWidth <= 32U);
1065  /* for DMA transfers bitsWidth must 8, 16, or 32 */
1066  DEV_ASSERT(!((master->driverType == FLEXIO_DRIVER_TYPE_DMA) &&
1067  (bitsWidth != 8U) && (bitsWidth != 16U) && (bitsWidth != 32U)
1068  ));
1069 
1070  baseAddr = g_flexioBase[master->flexioCommon.instance];
1071  resourceIndex = master->flexioCommon.resourceIndex;
1072 
1073  /* Check if driver is busy */
1074  DEV_ASSERT(master->driverIdle);
1075  /* Get the protocol clock frequency */
1076  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1077  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1078  DEV_ASSERT(inputClock > 0U);
1079 
1080  /* Compute divider */
1081  FLEXIO_I2S_DRV_MasterComputeBaudRateDivider(baudRate, &divider, inputClock);
1082 
1083  /* Configure SCK timer */
1084  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)(((((uint16_t)bitsWidth << 1U) - 1U) << 8U) + divider));
1085  /* Configure WS timer */
1086  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)((bitsWidth * ((divider + 1U) * 2U)) - 1U));
1087 
1088  master->bitsWidth = bitsWidth;
1089  master->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(bitsWidth);
1090 
1091  (void)clkErr;
1092  return STATUS_SUCCESS;
1093 }
1094 
1095 
1096 /*FUNCTION**********************************************************************
1097  *
1098  * Function Name : FLEXIO_I2S_DRV_MasterGetBaudRate
1099  * Description : Get the currently configured baud rate
1100  * Implements : FLEXIO_I2S_DRV_MasterGetBaudRate_Activity
1101  *
1102  *END**************************************************************************/
1104 {
1105  const FLEXIO_Type *baseAddr;
1106  uint32_t inputClock;
1107  uint16_t divider;
1108  uint16_t timerCmp;
1109  status_t clkErr;
1110  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1111 
1112  DEV_ASSERT(master != NULL);
1113  DEV_ASSERT(baudRate != NULL);
1114 
1115  baseAddr = g_flexioBase[master->flexioCommon.instance];
1116  resourceIndex = master->flexioCommon.resourceIndex;
1117 
1118  /* Get the protocol clock frequency */
1119  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1120  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1121  DEV_ASSERT(inputClock > 0U);
1122 
1123  /* Get the currently configured divider */
1124  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCK_TIMER(resourceIndex));
1125  divider = (uint16_t)(timerCmp & 0x00FFU);
1126 
1127  /* Compute baud rate: input_clock / (2 * (divider + 1)). Round to nearest integer */
1128  *baudRate = (inputClock + (uint32_t)divider + 1U) / (2U * ((uint32_t)divider + 1U));
1129 
1130  (void)clkErr;
1131  return STATUS_SUCCESS;
1132 }
1133 
1134 
1135 
1136 /*FUNCTION**********************************************************************
1137  *
1138  * Function Name : FLEXIO_I2S_DRV_MasterSendData
1139  * Description : Perform a non-blocking send transaction on the I2S bus
1140  * Implements : FLEXIO_I2S_DRV_MasterSendData_Activity
1141  *
1142  *END**************************************************************************/
1144  const uint8_t * txBuff,
1145  uint32_t txSize)
1146 {
1147  FLEXIO_Type *baseAddr;
1148  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1149 
1150  DEV_ASSERT(master != NULL);
1151  DEV_ASSERT(txBuff != NULL);
1152  DEV_ASSERT(txSize > 0U);
1153  DEV_ASSERT((txSize % (uint32_t)(master->byteWidth)) == 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  DEV_ASSERT((rxSize % (uint32_t)(master->byteWidth)) == 0U);
1252 
1253  baseAddr = g_flexioBase[master->flexioCommon.instance];
1254  resourceIndex = master->flexioCommon.resourceIndex;
1255 
1256  /* Check if driver is busy */
1257  DEV_ASSERT(master->driverIdle);
1258 
1259  master->rxData = rxBuff;
1260  master->rxRemainingBytes = rxSize;
1261  master->txData = NULL;
1262  master->txRemainingBytes = 0U;
1263  master->status = STATUS_BUSY;
1264  master->driverIdle = false;
1265 
1266  /* Enable timers and shifters */
1267  FLEXIO_I2S_DRV_MasterEnableTransfer(master);
1268 
1269  /* Enable transfer engine */
1270  switch (master->driverType)
1271  {
1273  /* Enable interrupts for Rx shifter */
1274  FLEXIO_SetShifterInterrupt(baseAddr,
1275  (uint8_t)(1U << RX_SHIFTER(resourceIndex)),
1276  true);
1277  FLEXIO_SetShifterErrorInterrupt(baseAddr,
1278  (uint8_t)(1U << RX_SHIFTER(resourceIndex)),
1279  true);
1280  break;
1282  /* Call FLEXIO_I2S_DRV_MasterCheckStatus once to send the first byte */
1283  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1284  break;
1286  FLEXIO_I2S_DRV_MasterStartDmaTransfer(master);
1287  break;
1288  default:
1289  /* Impossible type - do nothing */
1290  break;
1291  }
1292 
1293  /* For master we need to send a dummy char to start the clock.
1294  For slave just put a 0 in the buffer to keep the tx line clear while receiving. */
1295  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), 0x0, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
1296 
1297  return STATUS_SUCCESS;
1298 }
1299 
1300 
1301 /*FUNCTION**********************************************************************
1302  *
1303  * Function Name : FLEXIO_I2S_DRV_MasterReceiveDataBlocking
1304  * Description : Perform a blocking receive transaction on the I2S bus
1305  * Implements : FLEXIO_I2S_DRV_MasterReceiveDataBlocking_Activity
1306  *
1307  *END**************************************************************************/
1309  uint8_t * rxBuff,
1310  uint32_t rxSize,
1311  uint32_t timeout)
1312 {
1313  status_t status;
1314 
1315  /* mark transfer as blocking */
1316  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1317  {
1318  master->blocking = true;
1319  }
1320  /* Call FLEXIO_I2S_DRV_MasterReceiveData to start transfer */
1321  status = FLEXIO_I2S_DRV_MasterReceiveData(master, rxBuff, rxSize);
1322  if (status != STATUS_SUCCESS)
1323  {
1324  /* Transfer could not be started */
1325  master->blocking = false;
1326  return status;
1327  }
1328 
1329  /* Wait for transfer to end */
1330  return FLEXIO_I2S_DRV_MasterWaitTransferEnd(master, timeout);
1331 }
1332 
1333 
1334 /*FUNCTION**********************************************************************
1335  *
1336  * Function Name : FLEXIO_I2S_DRV_MasterTransferAbort
1337  * Description : Aborts a non-blocking I2S master transaction
1338  * Implements : FLEXIO_I2S_DRV_MasterTransferAbort_Activity
1339  *
1340  *END**************************************************************************/
1342 {
1343  DEV_ASSERT(master != NULL);
1344 
1345  /* Check if driver is busy */
1346  if (master->driverIdle)
1347  {
1348  return STATUS_SUCCESS;
1349  }
1350 
1351  master->status = STATUS_I2S_ABORTED;
1352  FLEXIO_I2S_DRV_MasterStopTransfer(master);
1353 
1354  return STATUS_SUCCESS;
1355 }
1356 
1357 
1358 /*FUNCTION**********************************************************************
1359  *
1360  * Function Name : FLEXIO_I2S_DRV_MasterGetStatus
1361  * Description : Get the status of the current non-blocking I2S master transaction
1362  * Implements : FLEXIO_I2S_DRV_MasterGetStatus_Activity
1363  *
1364  *END**************************************************************************/
1366 {
1367  uint32_t remainingBytes;
1368 
1369  DEV_ASSERT(master != NULL);
1370 
1371  /* Use rxRemainingBytes even for transmit; byte is not transmitted
1372  until rx shifter reports a receive event */
1373  remainingBytes = master->rxRemainingBytes;
1374 
1375  if (!master->driverIdle)
1376  {
1377  switch(master->driverType)
1378  {
1380  /* In polling mode advance the I2S transfer here */
1381  FLEXIO_I2S_DRV_MasterCheckStatus(master);
1382  break;
1383 
1385  /* In DMA mode just update the remaining count.
1386  DO NOT write master->rxRemainingBytes directly !!! */
1387  remainingBytes = EDMA_DRV_GetRemainingMajorIterationsCount(master->rxDMAChannel);
1388  break;
1389 
1390  default:
1391  /* Nothing */
1392  break;
1393  }
1394 
1395  }
1396 
1397  if (bytesRemaining != NULL)
1398  {
1399  *bytesRemaining = remainingBytes;
1400  }
1401 
1402  if (!master->driverIdle)
1403  {
1404  return STATUS_BUSY;
1405  }
1406  else
1407  {
1408  return master->status;
1409  }
1410 }
1411 
1412 
1413 /*FUNCTION**********************************************************************
1414  *
1415  * Function Name : FLEXIO_I2S_DRV_MasterSetRxBuffer
1416  * Description : Provide a buffer for receiving data.
1417  * Implements : FLEXIO_I2S_DRV_MasterSetRxBuffer_Activity
1418  *
1419  *END**************************************************************************/
1421  uint8_t * rxBuff,
1422  uint32_t rxSize)
1423 {
1424  DEV_ASSERT(master != NULL);
1425  DEV_ASSERT(rxBuff != NULL);
1426  DEV_ASSERT(rxSize > 0U);
1427 
1428  master->rxData = rxBuff;
1429  master->rxRemainingBytes = rxSize;
1430 
1431  return STATUS_SUCCESS;
1432 }
1433 
1434 
1435 /*FUNCTION**********************************************************************
1436  *
1437  * Function Name : FLEXIO_I2S_DRV_MasterSetTxBuffer
1438  * Description : Provide a buffer for transmitting data.
1439  * Implements : FLEXIO_I2S_DRV_MasterSetTxBuffer_Activity
1440  *
1441  *END**************************************************************************/
1443  const uint8_t * txBuff,
1444  uint32_t txSize)
1445 {
1446  DEV_ASSERT(master != NULL);
1447  DEV_ASSERT(txBuff != NULL);
1448  DEV_ASSERT(txSize > 0U);
1449 
1450  master->txData = txBuff;
1451  master->txRemainingBytes = txSize;
1452  /* for transmit we also count received bytes for end condition */
1453  master->rxRemainingBytes += txSize;
1454 
1455  return STATUS_SUCCESS;
1456 }
1457 
1458 
1459 /*FUNCTION**********************************************************************
1460  *
1461  * Function Name : FLEXIO_I2S_DRV_SlaveInit
1462  * Description : Initialize the FLEXIO_I2S slave mode driver
1463  * Implements : FLEXIO_I2S_DRV_SlaveInit_Activity
1464  *
1465  *END**************************************************************************/
1467  const flexio_i2s_slave_user_config_t * userConfigPtr,
1468  flexio_i2s_slave_state_t * slave)
1469 {
1470  status_t retCode;
1471  status_t osifError = STATUS_SUCCESS;
1472  uint8_t dmaReqTx;
1473  uint8_t dmaReqRx;
1474 
1475  DEV_ASSERT(slave != NULL);
1476  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
1477  /* Check that device was initialized */
1478  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
1479 
1480  /* Instruct the resource allocator that we need two shifters/timers */
1481  slave->flexioCommon.resourceCount = 2U;
1482  /* Common FlexIO driver initialization */
1483  retCode = FLEXIO_DRV_InitDriver(instance, (flexio_common_state_t *)slave);
1484  if (retCode != STATUS_SUCCESS)
1485  { /* Initialization failed, not enough resources */
1486  return retCode;
1487  }
1488  /* Initialize the semaphore */
1489  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1490  {
1491  osifError = OSIF_SemaCreate(&(slave->idleSemaphore), 0U);
1492  DEV_ASSERT(osifError == STATUS_SUCCESS);
1493  }
1494  /* Initialize driver-specific context structure */
1495  slave->driverType = userConfigPtr->driverType;
1496  slave->bitsWidth = userConfigPtr->bitsWidth;
1497  slave->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(userConfigPtr->bitsWidth);
1498  slave->driverIdle = true;
1499  slave->callback = userConfigPtr->callback;
1500  slave->callbackParam = userConfigPtr->callbackParam;
1501  slave->blocking = false;
1502  slave->txData = NULL;
1503  slave->txRemainingBytes = 0U;
1504  slave->rxData = NULL;
1505  slave->rxRemainingBytes = 0U;
1506  slave->master = false;
1507  slave->status = STATUS_SUCCESS;
1508 
1509  /* Configure device for I2S mode */
1510  FLEXIO_I2S_DRV_SlaveConfigure(slave, userConfigPtr);
1511 
1512  /* Set up transfer engine */
1513  switch (slave->driverType)
1514  {
1516  slave->flexioCommon.isr = FLEXIO_I2S_DRV_MasterCheckStatus;
1517  break;
1519  /* Nothing to do here, FLEXIO_I2S_DRV_MasterGetStatus() will handle the transfer */
1520  break;
1522  /* Store DMA channel numbers */
1523  slave->rxDMAChannel = userConfigPtr->rxDMAChannel;
1524  slave->txDMAChannel = userConfigPtr->txDMAChannel;
1525  /* Configure DMA request sources */
1526  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(slave->flexioCommon.resourceIndex)];
1527  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(slave->flexioCommon.resourceIndex)];
1528  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
1529  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
1530  break;
1531  default:
1532  /* Impossible type - do nothing */
1533  break;
1534  }
1535 
1536  (void)osifError;
1537  return STATUS_SUCCESS;
1538 }
1539 
1540 
1541 /*FUNCTION**********************************************************************
1542  *
1543  * Function Name : FLEXIO_I2S_DRV_SlaveSetConfig
1544  * Description : Set the baud rate and bit width for any subsequent I2S transfer
1545  * Implements : FLEXIO_I2S_DRV_SlaveSetConfig_Activity
1546  *
1547  *END**************************************************************************/
1549  uint8_t bitsWidth)
1550 {
1551  FLEXIO_Type *baseAddr;
1552  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1553 
1554  DEV_ASSERT(slave != NULL);
1555  DEV_ASSERT(bitsWidth <= 32U);
1556  /* for DMA transfers bitsWidth must 8, 16, or 32 */
1557  DEV_ASSERT(!((slave->driverType == FLEXIO_DRIVER_TYPE_DMA) &&
1558  (bitsWidth != 8U) && (bitsWidth != 16U) && (bitsWidth != 32U)
1559  ));
1560 
1561  baseAddr = g_flexioBase[slave->flexioCommon.instance];
1562  resourceIndex = slave->flexioCommon.resourceIndex;
1563 
1564  /* Check if driver is busy */
1565  DEV_ASSERT(slave->driverIdle);
1566 
1567  slave->bitsWidth = bitsWidth;
1568  slave->byteWidth = FLEXIO_I2S_DRV_ComputeByteWidth(bitsWidth);
1569 
1570  /* Configure SCK timer */
1571  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), (uint16_t)(((uint16_t)bitsWidth << 2U) - 3U));
1572  /* Configure WS timer */
1573  FLEXIO_SetTimerCompare(baseAddr, WS_TIMER(resourceIndex), (uint16_t)(((uint16_t)bitsWidth << 1U) - 1U));
1574 
1575  return STATUS_SUCCESS;
1576 }
1577 
1578 
1579 /*******************************************************************************
1580  * EOF
1581  ******************************************************************************/
void EDMA_DRV_SetMajorLoopIterationCount(uint8_t virtualChannel, uint32_t majorLoopCount)
Configures the number of major loop iterations.
Definition: edma_driver.c:1316
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.
uint32_t EDMA_DRV_GetRemainingMajorIterationsCount(uint8_t virtualChannel)
Returns the remaining major loop iteration count.
Definition: edma_driver.c:1346
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 EDMA_DRV_InstallCallback(uint8_t virtualChannel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:336
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
status_t EDMA_DRV_ConfigMultiBlockTransfer(uint8_t virtualChannel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t blockSize, uint32_t blockCount, bool disableReqOnCompletion)
Configures a multiple block data transfer with DMA.
Definition: edma_driver.c:662
status_t FLEXIO_I2S_DRV_MasterSetTxBuffer(flexio_i2s_master_state_t *master, const uint8_t *txBuff, uint32_t txSize)
Provide a buffer for transmitting data.
#define FLEXIO_INSTANCE_COUNT
Definition: S32K118.h:3350
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.
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
Slave configuration structure.
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
void EDMA_DRV_SetDestOffset(uint8_t virtualChannel, int16_t offset)
Configures the destination address signed offset for the eDMA channel.
Definition: edma_driver.c:1226
status_t FLEXIO_I2S_DRV_MasterDeinit(flexio_i2s_master_state_t *master)
De-initialize the FLEXIO_I2S master mode driver.
status_t EDMA_DRV_StopChannel(uint8_t virtualChannel)
Stops the eDMA channel.
Definition: edma_driver.c:952
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:255
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_driver.h:200
volatile uint32_t SHIFTBUFBIS[4u]
Definition: S32K118.h:3336
void EDMA_DRV_SetDestAddr(uint8_t virtualChannel, uint32_t address)
Configures the destination address for the eDMA channel.
Definition: edma_driver.c:1196
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
const clock_names_t g_flexioClock[(1u)]
Definition: flexio_common.c:65
status_t 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
FLEXIO_Type *const g_flexioBase[(1u)]
Definition: flexio_common.c:56
const uint8_t g_flexioDMASrc[(1u)][(4U)]
Definition: flexio_common.c:68
flexio_driver_type_t driverType
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
void EDMA_DRV_SetSrcAddr(uint8_t virtualChannel, uint32_t address)
Configures the source address for the eDMA channel.
Definition: edma_driver.c:1046
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
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.
flexio_device_state_t * g_flexioDeviceStatePtr[(1u)]
Definition: flexio_common.c:59
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
status_t EDMA_DRV_StartChannel(uint8_t virtualChannel)
Starts an eDMA channel.
Definition: edma_driver.c:921
status_t FLEXIO_I2S_DRV_MasterSetRxBuffer(flexio_i2s_master_state_t *master, uint8_t *rxBuff, uint32_t rxSize)
Provide a buffer for receiving data.
status_t EDMA_DRV_SetChannelRequest(uint8_t virtualChannel, uint8_t req)
Configures the DMA request for the eDMA channel.
Definition: edma_driver.c:983
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:266
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.
status_t FLEXIO_I2S_DRV_SlaveSetConfig(flexio_i2s_slave_state_t *slave, uint8_t bitsWidth)
Set the bit width for any subsequent I2S communication.