ADuCM4x50 Device Drivers API Reference Manual  Release 4.0.0.0
adi_sport.c
1 
23 /*============= I N C L U D E S =============*/
24 
25 #include <assert.h>
26 #include <string.h> /* memset declaration */
27 
28 #include <drivers/general/adi_drivers_general.h>
29 #include <adi_sport_config.h>
30 #include <drivers/sport/adi_sport.h>
31 #include <adi_cyclecount.h>
32 #include "adi_sport_def.h"
33 
34 #ifdef __ICCARM__
35 /*
36 * IAR MISRA C 2004 error suppressions.
37 *
38 * Pm123 (rule 8.5): there shall be no definition of objects or functions in a header file
39 * This isn't a header as such.
40 *
41 * Pm073 (rule 14.7): a function should have a single point of exit
42 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
43 * Multiple returns are used for error handling.
44 *
45 * Pm050 (rule 14.2): a null statement shall only occur on a line by itself
46 * Needed for null expansion of ADI_INSTALL_HANDLER and others.
47 *
48 * Pm088 (rule 17.4): pointer arithmetic should not be used.
49 * Relying on pointer arithmetic for buffer handling.
50 *
51 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
52 * The rule makes an exception for memory-mapped register accesses.
53 *
54 * Pm152: (MISRA C 2004 rule 17.4) array indexing shall only be applied to objects defined as an array type
55 * Accessing the DMA descriptors, which are defined in the system as a pointer to an array of descriptors
56 
57 */
58 #pragma diag_suppress=Pm026,Pm050,Pm073,Pm088,Pm123,Pm140,Pm143,Pm152,Pm153
59 #endif /* __ICCARM__ */
60 
61 /*============== D A T A ===============*/
62 
63 #define SPORT0_A_REGS ((volatile ADI_SPORT_TypeDef*)REG_SPORT0_CTL_A)
64 #define SPORT0_B_REGS ((volatile ADI_SPORT_TypeDef*)REG_SPORT0_CTL_B)
65 
66 #define SPORT0_A_CFG { 0u, 0u, 0u, 0u, 0u }
67 #define SPORT0_B_CFG { 0u, 0u, 0u, 0u, 0u }
68 
69 #define DXS_FIFO_IS_FULL(STAT) (((STAT) & BITM_SPORT_STAT_A_DXS) == BITM_SPORT_STAT_A_DXS)
70 #define DXS_FIFO_IS_EMPTY(STAT) (((STAT) & BITM_SPORT_STAT_A_DXS) == 0u)
71 
72 static ADI_SPORT_DEVICE_INFO gSportDevInfo [ADI_SPORT_NUM_INSTANCES][ADI_SPORT_NUM_CHANNELS] =
73 {
74  {/* registers configuration initial state DMA channel DMA IRQ SPORT IRQ handle */
75  {SPORT0_A_REGS, SPORT0_A_CFG, ADI_SPORT_STATE_UNINITIALIZED, SPORT0A_CHANn, DMA0_CH2_DONE_IRQn, SPORT_A_EVT_IRQn, NULL},
76  {SPORT0_B_REGS, SPORT0_B_CFG, ADI_SPORT_STATE_UNINITIALIZED, SPORT0B_CHANn, DMA0_CH3_DONE_IRQn, SPORT_B_EVT_IRQn, NULL},
77  },
78 };
79 
80 
81 static const ADI_SPORT_CONFIG gSportCfg[ADI_SPORT_NUM_INSTANCES][ADI_SPORT_NUM_CHANNELS] =
82 {
83  { /* configuration for SPORT 0 */
84  /* Configuration for half-SPORT A */
85  { /* SPORT_CTL register */
86  ((ADI_CFG_SPORT0A_ENABLE_FSMUXSEL) << BITP_SPORT_CTL_A_FSMUXSEL) |
87  ((ADI_CFG_SPORT0A_ENABLE_CKMUXSEL) << BITP_SPORT_CTL_A_CKMUXSEL) |
88  ((ADI_CFG_SPORT0A_LSB_FIRST) << BITP_SPORT_CTL_A_LSBF) |
89  ((ADI_CFG_SPORT0A_SERIAL_WLEN - 1u) << BITP_SPORT_CTL_A_SLEN) |
90  ((ADI_CFG_SPORT0A_INTERNAL_CLK) << BITP_SPORT_CTL_A_ICLK) |
91  ((ADI_CFG_SPORT0A_OPERATION_MODE) << BITP_SPORT_CTL_A_OPMODE) |
92  ((ADI_CFG_SPORT0A_CLOCK_EDGE) << BITP_SPORT_CTL_A_CKRE) |
93  ((ADI_CFG_SPORT0A_FS_REQUIRED) << BITP_SPORT_CTL_A_FSR) |
94  ((ADI_CFG_SPORT0A_INTERNAL_FS) << BITP_SPORT_CTL_A_IFS) |
95  ((ADI_CFG_SPORT0A_DATA_INDEPENDENT_FS) << BITP_SPORT_CTL_A_DIFS) |
96  ((ADI_CFG_SPORT0A_ACTIVE_LOW_FS) << BITP_SPORT_CTL_A_LFS) |
97  ((ADI_CFG_SPORT0A_LATE_FS) << BITP_SPORT_CTL_A_LAFS) |
98  ((ADI_CFG_SPORT0A_ENABLE_PACKING) << BITP_SPORT_CTL_A_PACK) |
99  ((ADI_CFG_SPORT0A_FS_ERROR_OPERATION) << BITP_SPORT_CTL_A_FSERRMODE) |
100  ((ADI_CFG_SPORT0A_GATED_CLOCK) << BITP_SPORT_CTL_A_GCLKEN),
101 
102  /* SPORT_DIV register */
103  ((ADI_CFG_SPORT0A_CLOCK_DIVISOR) << BITP_SPORT_DIV_A_CLKDIV) |
104  ((ADI_CFG_SPORT0A_FS_DIVISOR) << BITP_SPORT_DIV_A_FSDIV),
105 
106  /* SPORT_CONVT register */
107  ((ADI_CFG_SPORT0A_CONVT_WIDTH) << BITP_SPORT_CNVT_A_WID) |
108  ((ADI_CFG_SPORT0A_CONVT_POLARITY) << BITP_SPORT_CNVT_A_POL) |
109  ((ADI_CFG_SPORT0A_CONVT_FS_DURATION) << BITP_SPORT_CNVT_A_CNVT2FS),
110 
111  /* Default DMA data size for SPORT */
113 
114  /* Default DMA data increment for SPORT */
116  },
117 
118  /* Configuration for half-SPORT B */
119  { /* SPORT_CTL register */
120  ((ADI_CFG_SPORT0B_LSB_FIRST) << BITP_SPORT_CTL_B_LSBF) |
121  ((ADI_CFG_SPORT0B_SERIAL_WLEN - 1u) << BITP_SPORT_CTL_B_SLEN) |
122  ((ADI_CFG_SPORT0B_INTERNAL_CLK) << BITP_SPORT_CTL_B_ICLK) |
123  ((ADI_CFG_SPORT0B_OPERATION_MODE) << BITP_SPORT_CTL_B_OPMODE) |
124  ((ADI_CFG_SPORT0B_CLOCK_EDGE) << BITP_SPORT_CTL_B_CKRE) |
125  ((ADI_CFG_SPORT0B_FS_REQUIRED) << BITP_SPORT_CTL_B_FSR) |
126  ((ADI_CFG_SPORT0B_INTERNAL_FS) << BITP_SPORT_CTL_B_IFS) |
127  ((ADI_CFG_SPORT0B_DATA_INDEPENDENT_FS) << BITP_SPORT_CTL_B_DIFS) |
128  ((ADI_CFG_SPORT0B_ACTIVE_LOW_FS) << BITP_SPORT_CTL_B_LFS) |
129  ((ADI_CFG_SPORT0B_LATE_FS) << BITP_SPORT_CTL_B_LAFS) |
130  ((ADI_CFG_SPORT0B_ENABLE_PACKING) << BITP_SPORT_CTL_B_PACK) |
131  ((ADI_CFG_SPORT0B_FS_ERROR_OPERATION) << BITP_SPORT_CTL_B_FSERRMODE) |
132  ((ADI_CFG_SPORT0B_GATED_CLOCK) << BITP_SPORT_CTL_B_GCLKEN),
133 
134  /* SPORT_DIV register */
135  ((ADI_CFG_SPORT0B_CLOCK_DIVISOR) << BITP_SPORT_DIV_B_CLKDIV) |
136  ((ADI_CFG_SPORT0B_FS_DIVISOR) << BITP_SPORT_DIV_B_FSDIV),
137 
138  /* SPORT_CONVT register */
139  ((ADI_CFG_SPORT0B_CONVT_WIDTH) << BITP_SPORT_CNVT_B_WID) |
140  ((ADI_CFG_SPORT0B_CONVT_POLARITY) << BITP_SPORT_CNVT_B_POL) |
141  ((ADI_CFG_SPORT0B_CONVT_FS_DURATION) << BITP_SPORT_CNVT_B_CNVT2FS),
142 
143  /* Default DMA data size for SPORT */
145 
146  /* Default DMA data increment for SPORT */
148  }
149  }
150 };
151 
154 /*============= C O D E =============*/
155 
156 extern void SPORT0A_Int_Handler(void);
157 extern void SPORT0B_Int_Handler(void);
158 extern void DMA_SPORT0A_Int_Handler(void);
159 extern void DMA_SPORT0B_Int_Handler(void);
161 /*============= L O C A L F U N C T I O N S =============*/
162 
163 /*============= P U B L I C F U N C T I O N S =============*/
164 
194  const uint32_t nDevNum,
195  const ADI_SPORT_CHANNEL eChannel,
196  const ADI_SPORT_DIRECTION eDirection,
197  void *pMemory,
198  const uint32_t nMemSize,
199  ADI_SPORT_HANDLE * const phDevice
200  )
201 {
203 
204  assert(ADI_SPORT_MEMORY_SIZE == sizeof(ADI_SPORT_DEVICE)); /* validate the memory size macro */
205 #ifdef ADI_DEBUG
206  if (nDevNum >= ADI_SPORT_NUM_INSTANCES)
207  {
208  result = ADI_SPORT_INVALID_DEVICE_NUM; /* SPORT identifier must be within [0..ADI_SPORT_NUM_INSTANCES-1] */
209  }
210  else if (phDevice == NULL)
211  {
212  result = ADI_SPORT_INVALID_NULL_POINTER; /* the pointer to device handle must be valid */
213  }
214  else if (ADI_SPORT_MEMORY_SIZE != nMemSize)
215  {
216  result = ADI_SPORT_FAILED;
217  }
218  else if (ADI_SPORT_STATE_UNINITIALIZED != gSportDevInfo[nDevNum][eChannel].eState)
219  {
220  result = ADI_SPORT_DEVICE_IN_USE; /* the device instance must not be in use */
221  }
222  else
223 #endif /* ADI_DEBUG */
224  {
225  ADI_SPORT_DEVICE * pDevice = pMemory; /* Pointer to the SPORT device instance (from supplied memory) */
226  ADI_SPORT_DEVICE_INFO * sportInfo = &gSportDevInfo[nDevNum][eChannel]; /* SPORT info for HSPORT A or HSPORT B */
227  ADI_SPORT_CONFIG const * sportCfg = &gSportCfg[nDevNum][eChannel]; /* SPORT configuration for HSPORT A or HSPORT B */
228 
229  assert(eChannel < ADI_SPORT_NUM_CHANNELS);
230 
231  memset(pMemory, 0, nMemSize); /* clear the device instance data before initializing it */
232 
233  pDevice->pSportInfo = sportInfo; /* Initialize the pointer which provides the device information (HSPORT A or HSPORT B). */
234  pDevice->eDirection = eDirection; /* Initialize the direction (BEFORE calling sport_Configure)*/
235  pDevice->nHwError = (uint32_t) ADI_SPORT_HW_NO_ERR;
236 
237  adi_dma_Init(); /* Set up the DMA Controller. */
238  sport_Init(pDevice); /* Initialize the data transmission buffers */
239  sport_Configure(pDevice,sportCfg); /* Configure the SPORT */
240 
241  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(sportInfo->eDMAChnlID, sport_DmaErrorCallback, pDevice))
242  {
243  adi_sport_Close(pDevice);
245  }
246 
247  if (ADI_SPORT_SUCCESS == result)
248  {
249  ADI_SPORT_DEVICE_INFO * devInfo = &gSportDevInfo[nDevNum][eChannel];
250 
251  /* Create a "semaphore" (varies per OS) used for blocking buffer resource management. */
252  if (ADI_HALF_SPORT_A == eChannel)
253  {
254  SEM_CREATE(&pDevice->sportChannel, "SPORT0_A_SEM", ADI_SPORT_FAILED);
255  }else{
256  SEM_CREATE(&pDevice->sportChannel, "SPORT0_B_SEM", ADI_SPORT_FAILED);
257  }
258 
259  /* Change the state of the specified device */
260  ADI_INT_STATUS_ALLOC();
261  ADI_ENTER_CRITICAL_REGION();
262  devInfo->eState = ADI_SPORT_STATE_INITIALIZED;
263  devInfo->hDevice = pDevice;
264  ADI_EXIT_CRITICAL_REGION();
265  *phDevice = pDevice; /* Return the device handle to the application */
266  }
267  }
268 
269  return result;
270 }
271 
294 {
295  ADI_SPORT_RESULT result = ADI_SPORT_SUCCESS; /* return code */
296  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
297 #ifdef ADI_DEBUG
298  if (ADI_SPORT_SUCCESS == (result=ValidateHandle(pDevice))) /* Validate the given handle */
299 #endif /* ADI_DEBUG */
300  {
301  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo;
302 
303  /* Free up the device */
304  ADI_INT_STATUS_ALLOC();
305  ADI_ENTER_CRITICAL_REGION();
306  NVIC_DisableIRQ(pSportInfo->eIRQn); /* Disable SPORT event interrupts. */
307  NVIC_DisableIRQ(pSportInfo->eDMAn); /* Disable DMA SPORT interrupts. */
308  pSportInfo->eState = ADI_SPORT_STATE_UNINITIALIZED;
309  pSportInfo->hDevice = NULL; /* Free up the device memory. */
310  ADI_EXIT_CRITICAL_REGION();
311 
312  SEM_DELETE(&pDevice->sportChannel, ADI_SPORT_FAILED); /* Delete SPORT channel semaphore. */
313 
314  adi_dma_RegisterCallback(pSportInfo->eDMAChnlID, NULL, NULL); /* unregister the callback function in the DMA error handler */
315 
316  pSportInfo->pSportRegs->CTL_A = 0u;
317  }
318  return result;
319 }
320 
349  void * const pBuffer,
350  uint32_t const nNumBytes,
351  bool const bDMA
352  )
353 {
354  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* pointer to SPORT device instance */
355  ADI_SPORT_RESULT result = ADI_SPORT_SUCCESS; /* return code */
356 
357 #ifdef ADI_DEBUG
358  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg; /* short cut to SPORT configuration */
359 
360  if(ADI_SPORT_SUCCESS != (result=ValidateHandle(hDevice))) /* validate the given handle */
361  {
362  }
363  else if ( ((2u >= nNumBytes) && ((pDevice->pSportInfo->pSportRegs->CTL_A & BITM_SPORT_CTL_A_OPMODE) != 0u))
364  || (0u != (nNumBytes & ~(BITM_SPORT_NUMTRAN_A_VALUE))) /* buffer size limited by SPORT transmission capabilities */
365  )
366  {
368  }
369  else
370 #endif /* ADI_DEBUG */
371  /* Check that there is a free buffer to use for this transmit operation. pFreeBuffer
372  is the next buffer available, so if it is in use we can make the assumption that
373  there are no buffers available. The start address is set to NULL once the buffer
374  has finished being processed in "adi_sport_GetBuffer()".
375  */
376  if (NULL != pDevice->sportChannel.pFreeBuffer->pStartAddress)
377  {
379  }
380  else
381  {
382 #ifdef ADI_DEBUG
383  const uint32_t addr = (uint32_t) pBuffer;
384 
385  if (true == bDMA)
386  {
396  const uint32_t dataSizeInBytes = GetBytesPerSportData(pSportCfg->CTL);
397  const uint32_t full = nNumBytes / dataSizeInBytes; /* number of full data to transmit/receive */
398  const uint32_t partial = nNumBytes % dataSizeInBytes; /* number of partial data to transmit/receive */
399  const uint32_t misaligned = addr % dataSizeInBytes; /* number of data to transmit/receive */
400 
401  if ( (full > DMA_TRANSFER_LIMIT) /* number of data to process too large for DMA */
402  || (0u != partial) /* buffer size not a multiple of dataSizeInBytes */
403  || (0u != misaligned) /* buffer mis-aligned */
404  )
405  {
407  }
408  } else {
409  const uint32_t misAligned = addr % 4u;
410  const uint32_t invalidNum = nNumBytes % 4u;
411 
412  if ( (0u != misAligned) /* mis-aligned buffer */
413  || (0u != invalidNum) /* number of bytes not a multiple of 32-bit */
414  )
415  {
416  result = ADI_SPORT_INVALID_PARAMETER; /* reject the buffer submission */
417  }
418  }
419  if (ADI_SPORT_SUCCESS == result)
420 #endif /* ADI_DEBUG */
421  {
422  ADI_DT_CHANNEL * pSportChnl = &pDevice->sportChannel;
423 
424  pSportChnl->pFreeBuffer->pStartAddress = pBuffer; /* Set the start address of the data buffer */
425  pSportChnl->pFreeBuffer->nCount = nNumBytes; /* Set the buffer size */
426  pSportChnl->pFreeBuffer->nIndex = 0u; /* Initialize the buffer index to zero (1st data in buffer) */
427  pSportChnl->pFreeBuffer->bDMA = bDMA; /* Set the DMA boolean value. */
428  pSportChnl->pFreeBuffer->bInUse = true; /* this buffer is now being used by the SPORT */
429 
430  /* Now that this "pFreeBuffer" is no longer free for use, update the
431  "pFreeBuffer" to the next buffer. "pFreeBuffer" will only be updated
432  during the process of submitting a buffer or a read/write operation.
433  */
434  pSportChnl->pFreeBuffer = pSportChnl->pFreeBuffer->pNextBuffer;
435 
436  /* Set the data transfer mode in case it was #ADI_DT_MODE_NONE. This
437  will be set back to #ADI_DT_MODE_NONE once this transaction is complete.
438  Then, if a buffer is not currently active, set up the interrupts for
439  this transaction. Otherwise if a buffer is currently active, this will
440  be taken care of in the ISR.
441  */
442  if (pSportChnl->eDataTranferMode == ADI_DT_MODE_NONE) /* if the SPORT is available for a transmission */
443  {
444  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONBLOCKING;
445 
446  /* call an appropriate function based on mode in which device is operating */
447  if (true == bDMA) /* select a DMA driven or a core driven non-blocking transmission */
448  {
449  result = sport_SubmitBufferDmaMode(pDevice, pSportChnl->pFillBuffer);
450  } else {
451  result = sport_SubmitBufferIntMode(pDevice, pSportChnl->pFillBuffer);
452  }
453  }
454 
455  if(ADI_SPORT_SUCCESS != result) /* if an error occurred...*/
456  {
457  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONE; /* SPORT is available */
458  }
459  }
460  }
461 
462  return result;
463 }
464 
465 /*
466  * @brief Submit a buffer for SPORT Rx or Tx DMA driven transmission.
467  *
468  * @param [in] pDevice Pointer to SPORT device.
469  *
470  * @param [in] pBuffer Pointer to data transfer buffer information.
471  *
472  * @return Status
473  *
474  * - #ADI_SPORT_SUCCESS buffer successfully submitted to the DMA associated with the SPORT.
475  * - #ADI_SPORT_BUFFERS_NOT_SUBMITTED Failed to submit the buffer to the DMA associated with the SPORT.
476  */
478 static ADI_SPORT_RESULT sport_SubmitBufferDmaMode(ADI_SPORT_DEVICE * pDevice,
479  ADI_DT_BUFF_INFO * pBuff)
480 {
482  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* short cut to SPORT information */
483  ADI_SPORT_CONFIG * pSportCfg = &pSportInfo->sportCfg; /* short cut to SPORT configuration */
484 
485 #ifdef ADI_DEBUG
486  if ( (pBuff != pDevice->sportChannel.pFillBuffer) /* a submitted buffer should always be the current fill buffer */
487  || (true != pBuff->bInUse) /* Processed buffers should already be marked as being used */
488  || (0u != pBuff->nIndex) /* processing should start from index 0 */
489  )
490  {
491  result = ADI_SPORT_FAILED;
492  }
493  else
494 #endif
495  {
496  volatile ADI_SPORT_TypeDef* pSportRegs = pSportInfo->pSportRegs;/* short cut to SPORT registers */
497  const uint32_t dmaChnlId = (uint32_t) pSportInfo->eDMAChnlID; /* identifier for the DMA channel to be used */
498  const uint32_t dmaChnlBit = (1u << dmaChnlId); /* bit representing the DMA channel to be used */
499 
510  const uint32_t dmaIncNone = (uint32_t) ADI_DMA_INCR_NONE;
511  const uint32_t dmaDcc = (uint32_t) DMA_ENUM_CTL_CYCLE_CTL_BASIC;
512  const uint32_t bytesPerData = GetBytesPerSportData(pSportCfg->CTL);
513 
514  const uint32_t dataSizeInBytes = (1u << pSportCfg->DMA_WIDTH); /* number of bytes in each data to transmit/receive */
515  uint32_t numDmaData = pBuff->nCount / dataSizeInBytes; /* number of DMA data to transmit/receive */
516  const uint32_t dmaDataEnd = (pBuff->nCount - dataSizeInBytes); /* position of last <8,16,32>-bit data in the DMA transfer being setup */
517  const uint32_t startAddress = (uint32_t) pBuff->pStartAddress; /* address of the first byte in the data buffer */
518  const uint32_t numSportData = pBuff->nCount / bytesPerData; /* number of SPORT data to transmit/receive */
519 
520  assert(pBuff->nCount == (numSportData * bytesPerData));
521  assert(numSportData <= 0xFFFu);
522  assert(0u == (pBuff->nCount % dataSizeInBytes));
523  assert(numDmaData <= DMA_TRANSFER_LIMIT);
524  assert((ADI_SPORT_DIR_RX == pDevice->eDirection) || (ADI_SPORT_DIR_TX == pDevice->eDirection));
525  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
526 
527  pSportRegs->CTL_A = 0u; /* make sure SPORT is disable */
528  pADI_DMA0->SRCADDR_CLR = dmaChnlBit; /* Clear source address decrement for TX channel DMA. */
529  pADI_DMA0->EN_SET = dmaChnlBit; /* Enable channel DMA. */
530  pADI_DMA0->RMSK_CLR = dmaChnlBit; /* Enable SPORT peripheral to generate DMA requests. */
531  pADI_DMA0->ALT_CLR = dmaChnlBit; /* Set the primary control data structure as the current DMA descriptor. */
532  pADI_DMA0->PRI_SET = dmaChnlBit;
533 
534  if (ADI_SPORT_DIR_RX == pDevice->eDirection)
535  {
536  pPrimaryCCD[dmaChnlId].DMASRCEND = (uint32_t) &pSportRegs->RX_A; /* address of the last src data in the DMA transfer being setup */
537  pPrimaryCCD[dmaChnlId].DMADSTEND = startAddress + dmaDataEnd; /* address of the last dst data in the DMA transfer being setup */
538  pPrimaryCCD[dmaChnlId].DMACDC =
539  (pSportCfg->DMA_INC << ((uint32_t)DMA_BITP_CTL_DST_INC)) | /* destination address incremented by N bytes */
540  (dmaIncNone << ((uint32_t)DMA_BITP_CTL_SRC_INC)); /* source address not incremented */
541  }
542  else /* ADI_SPORT_DIR_TX */
543  {
544  pPrimaryCCD[dmaChnlId].DMASRCEND = startAddress + dmaDataEnd; /* address of the last src data in the DMA transfer being setup */
545  pPrimaryCCD[dmaChnlId].DMADSTEND = (uint32_t) &pSportRegs->TX_A; /* address of the last dst data in the DMA transfer being setup */
546  pPrimaryCCD[dmaChnlId].DMACDC =
547  (dmaIncNone << ((uint32_t)DMA_BITP_CTL_DST_INC)) | /* destination address not incremented */
548  (pSportCfg->DMA_INC << ((uint32_t)DMA_BITP_CTL_SRC_INC)); /* source address incremented by N byte */
549 
553  if (numDmaData < numSportData)
554  {
555  pPrimaryCCD[dmaChnlId].DMASRCEND = startAddress + dmaDataEnd + dataSizeInBytes; /* address of the last src data in the DMA transfer being setup */
556  numDmaData++;
557  }
558  }
559  pPrimaryCCD[dmaChnlId].DMACDC |=
560  (pSportCfg->DMA_WIDTH << ((uint32_t)DMA_BITP_CTL_SRC_SIZE)) | /* source data size in bytes */
561  (0u << ((uint32_t) DMA_BITP_CTL_R_POWER)) |
562  ((numDmaData - 1u) << ((uint32_t)DMA_BITP_CTL_N_MINUS_1)) | /* number of DMA transfers (minus 1) */
563  (dmaDcc << ((uint32_t)DMA_BITP_CTL_CYCLE_CTL));
564 
565  ADI_INT_STATUS_ALLOC();
566  ADI_ENTER_CRITICAL_REGION();
567  pDevice->pSportInfo->eState = ADI_SPORT_STATE_DATA_FLOW_ENABLED;
568  pSportRegs->NUMTRAN_A = numSportData;
569 
570  /* Enable SPORT DMA request interrupt for the SPORT tx channel. */
571  NVIC_ClearPendingIRQ(pSportInfo->eIRQn);
572  NVIC_ClearPendingIRQ(pSportInfo->eDMAn);
573 
574  uint32_t ien_a = ((uint32_t)BITM_SPORT_IEN_A_SYSDATERR) |
575  ((uint32_t)BITM_SPORT_IEN_A_FSERRMSK) |
576  ((uint32_t)BITM_SPORT_IEN_A_DERRMSK);
577  if (ADI_SPORT_DIR_RX == pDevice->eDirection)
578  {
579  /* Allow SPORT DMA interrupt handling to mark SPORT Rx as complete */
580  NVIC_EnableIRQ(pSportInfo->eDMAn);
581  }
582  else
583  {
584  /* SPORT DMA Tx is complete when TFI is raised: enable TFI */
585  ien_a |= ((uint32_t)BITM_SPORT_IEN_A_TF);
586  }
587 
588  NVIC_EnableIRQ(pSportInfo->eIRQn);
589 
590  pSportRegs->IEN_A = ien_a;
591  pSportRegs->CTL_A = pSportCfg->CTL |
592  ((uint32_t)BITM_SPORT_CTL_A_SPEN) |
593  ((uint32_t)BITM_SPORT_CTL_A_DMAEN);
594  ADI_EXIT_CRITICAL_REGION();
595 
596  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
597  }
598  return result;
599 }
600 
602 /*
603  * @brief Submit a buffer for SPORT Rx or Tx core driven transmission.
604  *
605  * @details Submit a buffer for SPORT Rx or Tx core driven transmission.
606  * The buffer must be 32-bit aligned and contain N * 32-bit data.
607  *
608  * @param [in] pDevice Pointer to SPORT device.
609  *
610  * @param [in] pBuffer Pointer to data transfer buffer information.
611  *
612  * @return Status
613  *
614  * - #ADI_SPORT_SUCCESS Successfully submitted the buffer for data transfer.
615  *
616  * - #ADI_SPORT_BUFFERS_NOT_SUBMITTED No free descriptor for data transfer.
617  *
618  *
619  */
620 static ADI_SPORT_RESULT sport_SubmitBufferIntMode(ADI_SPORT_DEVICE * pDevice, ADI_DT_BUFF_INFO * pBuff)
621 {
623 #ifdef ADI_DEBUG
624  if ( (pBuff != pDevice->sportChannel.pFillBuffer) /* a submitted buffer should always be the current fill buffer */
625  || (true != pBuff->bInUse) /* Processed buffers should already be marked as being used */
626  || (0u != pBuff->nIndex) /* processing should start from index 0 */
627  )
628  {
629  result = ADI_SPORT_FAILED;
630  }
631  else
632 #endif /* ADI_DEBUG */
633  {
634  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
635  volatile ADI_SPORT_TypeDef * pSportRegs = pDevice->pSportInfo->pSportRegs;
636  uint32_t ctl = pSportCfg->CTL;
637  uint32_t bytesPerData = GetBytesPerSportData(ctl);
638 
648  /* use the SPORT configuration to setup the SPORT registers */
649 
650  pBuff->nCount /= bytesPerData; /* number of data to be transmitted */
651 
652 #ifdef ADI_DEBUG
653  uint32_t pack = SPORT_GET_PACKEN(pSportCfg->CTL);
654  assert( ((9u > bytesPerData) && (1u == pack)) || ((17u > bytesPerData) && (2u == pack)) || (0u == pack));
655 #endif
656  assert(pBuff->nCount <= 0xFFFu);
657  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
658 
659  ADI_INT_STATUS_ALLOC();
660  ADI_ENTER_CRITICAL_REGION();
661  pSportRegs->CTL_A = 0u; /* make sure SPORT is disable */
662  pSportRegs->NUMTRAN_A = pBuff->nCount;
663  pDevice->pSportInfo->eState = ADI_SPORT_STATE_DATA_FLOW_ENABLED;
664 
665  /* Enable SPORT Interrupt. */
666  NVIC_ClearPendingIRQ(pDevice->pSportInfo->eIRQn);
667  NVIC_EnableIRQ(pDevice->pSportInfo->eIRQn);
668  pSportRegs->IEN_A |= ((uint32_t) ( BITM_SPORT_IEN_A_DATA
669  | BITM_SPORT_IEN_A_SYSDATERR
670  | BITM_SPORT_IEN_A_FSERRMSK
671  | BITM_SPORT_IEN_A_DERRMSK
672  | BITM_SPORT_IEN_A_TF
673  )
674  );
675  pSportRegs->CTL_A = pSportCfg->CTL | ((uint32_t)BITM_SPORT_CTL_A_SPEN);
676  ADI_EXIT_CRITICAL_REGION();
677  }
678  return result;
679 }
680 
718  void ** const ppBuffer,
719  uint32_t * pHwError)
720 {
722  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) hDevice; /* Pointer to SPORT device instance */
723 
724  *ppBuffer = NULL;
725 #ifdef ADI_DEBUG
726  if (ADI_SPORT_SUCCESS != (result=ValidateHandle(pDevice))) /* Validate the given handle */
727  {
728  }
729  else
730 #endif /* ADI_DEBUG */
731  if (NULL != pDevice->pfCallback)
732  {
733  result = ADI_SPORT_FAILED;
734  } else {
735  ADI_DT_CHANNEL * pSportChnl = &pDevice->sportChannel;
736 
737  SEM_PEND(pSportChnl,ADI_SPORT_FAILED); /* wait for a submitted buffer to be processed */
738 
739  ADI_INT_STATUS_ALLOC();
740  ADI_ENTER_CRITICAL_REGION();
741  *pHwError = pDevice->nHwError;
742  pDevice->nHwError = 0u;
743  *ppBuffer = pSportChnl->pActiveBuffer->pStartAddress; /* return the buffer start address in *ppBuffer */
744  pSportChnl->pActiveBuffer->pStartAddress = NULL; /* clear the free buffer address */
745  pSportChnl->pActiveBuffer = pSportChnl->pActiveBuffer->pNextBuffer;
746  ADI_EXIT_CRITICAL_REGION();
747  if (0u != *pHwError)
748  {
749  result = ADI_SPORT_HW_ERROR;
750  }
751  }
752  return result;
753 }
754 
779  bool * const pbAvailable)
780 {
782  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) hDevice; /* Pointer to SPORT device instance */
783 
784  *pbAvailable = false;
785 #ifdef ADI_DEBUG
786  if (ADI_SPORT_SUCCESS != (result=ValidateHandle(pDevice))) /* Validate the given handle */
787  {
788  }
789  else
790 #endif /* ADI_DEBUG */
791  if (NULL != pDevice->pfCallback)
792  {
794  }
795  else
796  {
797  ADI_DT_BUFF_INFO * pActiveBuffer = pDevice->sportChannel.pActiveBuffer;
798 
799  if (pActiveBuffer->pStartAddress == NULL)
800  {
802  }
803  else if (false == pActiveBuffer->bInUse) /* this buffer has been processed by the SPORT */
804  {
805  *pbAvailable = true;
806  }
807  else
808  {
809  }
810  }
811  return result;
812 }
813 
837  ADI_CALLBACK const pfCallback,
838  void * const pCBparam)
839 {
841  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
842 #ifdef ADI_DEBUG
843  /* Validate the given handle */
844  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
845  {
846  }
847  /* Check if the data flow is already enabled */
848  else if (ADI_SPORT_STATE_DATA_FLOW_ENABLED == pDevice->pSportInfo->eState)
849  {
850  /* Not allowed to register a callback if the data flow is enabled. */
852  }
853  else
854 #endif /* ADI_DEBUG */
855  {
856  ADI_INT_STATUS_ALLOC();
857  ADI_ENTER_CRITICAL_REGION();
858  pDevice->pfCallback = pfCallback; /* Store the address of the callback function */
859  pDevice->pCBParam = pCBparam; /* Store the call back parameter */
860  ADI_EXIT_CRITICAL_REGION();
861  }
862  return result;
863 }
864 
900  const uint8_t nWordLength,
901  const ADI_SPORT_PACKING_MODE ePackMode,
902  const bool bLSBFirst
903  )
904 {
906  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
907 #ifdef ADI_DEBUG
908  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
909  {
910  }
911  if(pDevice->pSportInfo->eState == ADI_SPORT_STATE_DATA_FLOW_ENABLED) /* Not allowed to change when data flow is enabled */
912  {
914  }
915  else
916 #endif /* ADI_DEBUG */
917  if (nWordLength > SPORT_WORD_TRANSFER_LENGTH)
918  {
920  }
921  else
922  {
923  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* short cut to SPORT information */
924  ADI_SPORT_CONFIG * pSportCfg = &pSportInfo->sportCfg; /* short cut to SPORT configuration */
925  const uint32_t bytesPerData = ((nWordLength < 9u) ? (1u) : ((nWordLength < 17u) ? (2u) : (4u)));
926 
927  const uint32_t wordPos = (uint32_t) BITP_SPORT_CTL_A_SLEN;
928  const uint32_t wordLen = (uint32_t) nWordLength;
929  const uint32_t ctlSlen = (wordLen - 1u) << wordPos;
930  const uint32_t packMode = (uint32_t) ePackMode;
931  const uint32_t ctlSlenBits = (0x1Fu << wordPos);
932  const uint32_t ctlDataMask = ~(BITM_SPORT_DATA_CONFIG | ctlSlenBits | BITM_SPORT_CTL_A_LSBF);
933 
934  uint32_t ctl = pDevice->pSportInfo->sportCfg.CTL;
935  ctl &= ctlDataMask; /* clear all the fields(i.e Set to "0" ) */
936  ctl |= (packMode | ctlSlen); /* assign packing and slen information */
937  if (true == bLSBFirst)
938  {
939  ctl |= BITM_SPORT_CTL_A_LSBF; /* set the the LSB first field */
940  }
941  pDevice->pSportInfo->sportCfg.CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
942 
943  SPORT_CHECK_CFG_CTL(pDevice->pSportInfo->sportCfg.CTL);
944 
945  switch (bytesPerData)
946  {
947  case 1u:
948  if (((uint32_t) ADI_SPORT_8BIT_PACKING) == packMode)
949  {
950  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
951  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
952  } else {
953  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_1_BYTE;
954  pSportCfg->DMA_INC = ADI_DMA_INCR_1_BYTE;
955 
956  assert(((uint32_t) ADI_SPORT_NO_PACKING) == packMode);
957  }
958  break;
959 
960  case 2u:
961  if (((uint32_t) ADI_SPORT_16BIT_PACKING) == packMode)
962  {
963  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
964  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
965  } else {
966  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_2_BYTE;
967  pSportCfg->DMA_INC = ADI_DMA_INCR_2_BYTE;
968 
969  assert(((uint32_t) ADI_SPORT_NO_PACKING) == packMode);
970  }
971  break;
972 
973  default:
974  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
975  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
976  assert((4u == bytesPerData) || (((uint32_t) ADI_SPORT_NO_PACKING) == packMode));
977  break;
978  }
979  }
980  return result;
981 }
982 
1032  const uint16_t nClockRatio,
1033  const bool bUseIntlClock,
1034  const bool bRisingEdge,
1035  const bool bGatedClk)
1036 {
1038  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
1039 
1040 #ifdef ADI_DEBUG
1041  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
1042  {
1043  }
1044  else if (ADI_SPORT_STATE_DATA_FLOW_ENABLED == pDevice->pSportInfo->eState)
1045  {
1047  }
1048  else
1049 #endif /* ADI_DEBUG */
1050  {
1051  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1052  uint32_t clockRatio = (uint32_t) nClockRatio;
1053 
1054  uint32_t ctl = pSportCfg->CTL;
1055  uint32_t dv = pSportCfg->DIV;
1056 
1057  ctl &= ~BITM_SPORT_CLOCK_CONFIG; /* clear all clock configuration fields */
1058 
1059  dv &= ~BITM_SPORT_DIV_A_CLKDIV;
1060  dv |= (clockRatio & BITM_SPORT_DIV_A_CLKDIV); /* update the clock divisior value */
1061 
1062  if (true == bUseIntlClock)
1063  {
1064  ctl |= BITM_SPORT_CTL_A_ICLK; /* select the internal clock */
1065  }
1066  if (true == bRisingEdge)
1067  {
1068  ctl |= BITM_SPORT_CTL_A_CKRE; /* select the rising edge of the clock */
1069  }
1070  if (true == bGatedClk)
1071  {
1072  ctl |= BITM_SPORT_CTL_A_GCLKEN; /* Enable the Gated clock */
1073  }
1074  pDevice->pSportInfo->pSportRegs->DIV_A = pSportCfg->DIV = dv; /* DIV value set */
1075  pSportCfg->CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
1076 
1077  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1078  }
1079  return result;
1080 }
1081 
1163  const uint16_t nFsDivisor,
1164  const bool bFSRequired,
1165  const bool bInternalFS,
1166  const bool bDataFS,
1167  const bool bActiveLowFS,
1168  const bool bLateFS,
1169  const bool bFSErrorOperation)
1170 {
1171  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
1173 
1174 #ifdef ADI_DEBUG
1175  /* Validate the given handle */
1176  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
1177  {
1178  }
1179  else if(pDevice->pSportInfo->eState == ADI_SPORT_STATE_DATA_FLOW_ENABLED)
1180  {
1182  }
1183  else
1184 #endif /* ADI_DEBUG */
1185  {
1186  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1187  const uint32_t fsDivisor = (uint32_t) nFsDivisor;
1188 
1189  uint32_t ctl = pSportCfg->CTL;
1190  uint32_t dv = pSportCfg->DIV;
1191 
1192  dv &= ~BITM_SPORT_DIV_A_FSDIV; /* clear all the fields of frame sync */
1193  dv |= (fsDivisor << BITP_SPORT_DIV_A_FSDIV);
1194 
1195  ctl &= ~BITM_SPORT_FS_CONFIG; /* clear all the fields of frame sync */
1196 
1197  if ((ADI_SPORT_DIR_RX == pDevice->eDirection) || (true == bDataFS))
1198  {
1199  ctl |= BITM_SPORT_CTL_A_DIFS; /* Set this bit when SPORT is opened in RX mode */
1200  }
1201  if (true == bFSRequired) /* "Frame sync required" is reserved when device */
1202  { /* is operating in I2S and MC mode */
1203  ctl |= BITM_SPORT_CTL_A_FSR; /* Frame Sync(FS) is required */
1204  }
1205  if (true == bInternalFS)
1206  {
1207  ctl |= BITM_SPORT_CTL_A_IFS; /* Select the internal Frame Sync(FS)*/
1208  }
1209  if (true == bActiveLowFS)
1210  {
1211  ctl |= BITM_SPORT_CTL_A_LFS; /* Select the Active High Frame Sync(FS)*/
1212  }
1213  if (true == bLateFS)
1214  {
1215  ctl |= BITM_SPORT_CTL_A_LAFS; /* Select the Late Frame Sync(FS)*/
1216  }
1217  if (true == bFSErrorOperation)
1218  {
1219  ctl |= BITM_SPORT_CTL_A_FSERRMODE; /* Select the edge sensitive Frame Sync(FS)*/
1220  }
1221  pDevice->pSportInfo->pSportRegs->DIV_A = pSportCfg->DIV = dv; /* DIV value set */
1222  pSportCfg->CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
1223 
1224  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1225  }
1226  return result;
1227 }
1228 
1259  const bool bUseOtherFS,
1260  const bool bUseOtherClk)
1261 {
1263  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *)hDevice; /* Pointer to SPORT device instance */
1264 #ifdef ADI_DEBUG
1265  if((result = ValidateHandle(pDevice)) != ADI_SPORT_SUCCESS) /* Validate the given handle */
1266  {
1267  }
1268  else if (pDevice->pSportInfo->eState == ADI_SPORT_STATE_DATA_FLOW_ENABLED)
1269  {
1271  }
1272  else
1273 #endif /* ADI_DEBUG */
1274  {
1275  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1276  uint32_t ctl = pSportCfg->CTL;
1277 
1278  /* clear the muxing fields of the control register 2 */
1279  ctl &= (uint32_t)(~(BITM_SPORT_CTL_A_CKMUXSEL | BITM_SPORT_CTL_A_FSMUXSEL));
1280  if (true == bUseOtherFS)
1281  {
1282  ctl |= BITM_SPORT_CTL_A_FSMUXSEL; /* Use the the frame sync of other half sport*/
1283  }
1284  if(bUseOtherClk == true)
1285  {
1286  ctl |= BITM_SPORT_CTL_A_CKMUXSEL; /* Use the the clock of other half sport*/
1287  }
1288  pSportCfg->CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
1289 
1290  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1291  }
1292 
1293  return result;
1294 }
1323  const uint8_t nFSDuration,
1324  const uint8_t nWidth,
1325  const bool bActiveLow)
1326 {
1328  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) hDevice; /* Pointer to SPORT device instance */
1329 
1330 #ifdef ADI_DEBUG /* Validate the given handle */
1331  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
1332  {
1333  }
1334  else if (ADI_SPORT_STATE_DATA_FLOW_ENABLED == pDevice->pSportInfo->eState)
1335  {
1337  }
1338  else
1339 #endif /* ADI_DEBUG */
1340  {
1341  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1342  uint32_t cnvt = pSportCfg->TIM_CONVT;
1343 
1344  /* clear the muxing fields of the control register 2 */
1345  cnvt &= (uint32_t)(~(BITM_SPORT_CNVT_A_POL | BITM_SPORT_CNVT_A_WID | BITM_SPORT_CNVT_A_CNVT2FS ));
1346  cnvt |= (((uint32_t) nFSDuration << ((uint32_t) BITP_SPORT_CNVT_A_CNVT2FS)) | ((uint32_t) nWidth));
1347  if(bActiveLow == true)
1348  {
1349  cnvt |= ((uint32_t) BITM_SPORT_CNVT_A_POL); /* Use the the clock of other half sport*/
1350  }
1351  pDevice->pSportInfo->pSportRegs->CNVT_A = pSportCfg->TIM_CONVT = cnvt;
1352  }
1353  return result;
1354 }
1355 
1370 static inline void sport_Init (ADI_SPORT_DEVICE *pDevice)
1371 {
1372  uint32_t i;
1373  ADI_DT_CHANNEL *pChannel = &pDevice->sportChannel;
1374  ADI_DT_BUFF_INFO *pBufInfo = &pChannel->BufInfo[0]; /* initialize this variable with the first array element */
1375  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* short cut to SPORT information */
1376  ADI_SPORT_CONFIG * pSportCfg = &pSportInfo->sportCfg; /* short cut to SPORT configuration */
1377  const uint32_t bytesPerData = GetBytesPerSportData(pSportCfg->CTL); /* number of bytes in SPORT data (1, 2, or 4) */
1378  const uint32_t packMode = SPORT_GET_PACKEN(pSportCfg->CTL); /* SPORT data pack mode */
1379 
1380  /* Initialize the all descriptors. Make it circular. */
1381  for(i = 0u; i < ADI_DT_BUFNUM; i++)
1382  {
1383  pBufInfo[i].pStartAddress = NULL;
1384  pBufInfo[i].nCount = 0u;
1385  pBufInfo[i].nIndex = 0u;
1386  pBufInfo[i].pNextBuffer = &pBufInfo[(i+1u) % ADI_DT_BUFNUM]; /* link the buffers in a circular way */
1387  }
1388  pChannel->pFreeBuffer = &pChannel->BufInfo[0u]; /* the first free buffer is the first array element */
1389  pChannel->pActiveBuffer = &pChannel->BufInfo[0u]; /* the first active buffer is the first array element */
1390  pChannel->pFillBuffer = &pChannel->BufInfo[0u]; /* the first fill buffer is the first array element */
1391 
1392  switch (bytesPerData)
1393  {
1394  case 1u:
1395  if (SPORT_BIT_PACK_8 == packMode)
1396  {
1397  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1398  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1399  } else {
1400  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_1_BYTE;
1401  pSportCfg->DMA_INC = ADI_DMA_INCR_1_BYTE;
1402 
1403  assert(SPORT_BIT_PACK_NONE == packMode);
1404  }
1405  break;
1406 
1407  case 2u:
1408  if (SPORT_BIT_PACK_16 == packMode)
1409  {
1410  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1411  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1412  } else {
1413  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_2_BYTE;
1414  pSportCfg->DMA_INC = ADI_DMA_INCR_2_BYTE;
1415 
1416  assert(SPORT_BIT_PACK_NONE == packMode);
1417  }
1418  break;
1419 
1420  default:
1421  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1422  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1423  assert((4u == bytesPerData) || (SPORT_BIT_PACK_NONE == packMode));
1424  break;
1425  }
1426 }
1427 
1428 /*
1429  * @brief Configure the registers with the half-SPORT
1430  *
1431  * @param [in] hDevice Device handle to SPORT device.
1432  * @param [in] sportCfg SPORT configuration to be used.
1433  *
1434  * @return None
1435  */
1436 static inline void sport_Configure (ADI_SPORT_DEVICE *pDevice, ADI_SPORT_CONFIG const * sportCfg)
1437 {
1438  /* Configure the SPORT device using static configuration parameters.
1439  * pSportInfo is mapped to one of the half-SPORT available; this is the
1440  * half-SPORT configured. (CTL_A, DIV_A, CNVT_A and NUMTRAN_A map either
1441  * to half-SPORT A registers or half-SPORT B registers, depending on
1442  * sportRegs.)
1443  */
1444  volatile ADI_SPORT_TypeDef * sportRegs = pDevice->pSportInfo->pSportRegs;
1445  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1446 
1447  /* record the SPORT default configuration */
1448  memcpy(pSportCfg, sportCfg, sizeof(ADI_SPORT_CONFIG));
1449 
1450  switch (pDevice->eDirection) /* Set the direction of operation */
1451  {
1452  case ADI_SPORT_DIR_RX:
1453  pSportCfg->CTL &= ~BITM_SPORT_CTL_A_SPTRAN;
1454  break;
1455  case ADI_SPORT_DIR_TX:
1456  pSportCfg->CTL |= BITM_SPORT_CTL_A_SPTRAN;
1457  break;
1458  default:
1459  assert(0);
1460  break;
1461  }
1462  /* use the SPORT configuration to setup the SPORT registers */
1463  sportRegs->CTL_A = pSportCfg->CTL;
1464  sportRegs->DIV_A = pSportCfg->DIV;
1465  sportRegs->CNVT_A = pSportCfg->TIM_CONVT;
1466  sportRegs->NUMTRAN_A = 0u;
1467 
1468  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1469 }
1470 
1471 #ifdef ADI_DEBUG
1472 static ADI_SPORT_RESULT ValidateHandle(ADI_SPORT_HANDLE const hDevice)
1473 {
1475  ADI_SPORT_DEVICE * pInDevice = (ADI_SPORT_DEVICE*) hDevice;
1476  ADI_SPORT_DEVICE_INFO *poDeviceInfo = &gSportDevInfo[0][0];
1477  uint32_t i;
1478 
1479  /* Pointer to SPORT device instance */
1480  for (i=0u; i<(ADI_SPORT_NUM_INSTANCES << 1u); i++) /* 2 half-devices per SPORT */
1481  {
1482  if (pInDevice == poDeviceInfo->hDevice)
1483  {
1484  result = ADI_SPORT_SUCCESS;
1485  break;
1486  }
1487  poDeviceInfo++;
1488  }
1489  return result;
1490 }
1491 #endif /* ADI_DEBUG */
1492 
1493 /* mask for events to be recorded in the driver HW error */
1494 #define recEvt ((uint32_t) (BITM_SPORT_STAT_A_SYSDATERR | BITM_SPORT_STAT_A_FSERR | BITM_SPORT_STAT_A_DERR))
1495 
1496 /* bits to be cleared by the ISR */
1497 #define clrEvt ((recEvt | BITM_SPORT_STAT_A_TFI))
1498 
1499 static void sport_Terminate(ADI_SPORT_DEVICE * pDevice)
1500 {
1501  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* get SPORT device information */
1502  volatile ADI_SPORT_TypeDef * pRegs = pSportInfo->pSportRegs; /* access SPORT registers */
1503 
1504  ADI_DT_CHANNEL * pSportChnl = &pDevice->sportChannel;
1505  ADI_DT_BUFF_INFO * pBuff = pSportChnl->pFillBuffer;
1506 
1507  pRegs->CTL_A &= ~BITM_SPORT_CTL_A_SPEN; /* disable SPORT */
1508  pRegs->IEN_A &= ~(BITM_SPORT_IEN_A_TF | BITM_SPORT_IEN_A_DATA); /* disable SPORT interrupts */
1509  pRegs->NUMTRAN_A = 0u;
1510 
1511 #ifdef ADI_DEBUG
1512  {
1513  /* ============================================= */
1514  /* Check the number of data transmitted/received */
1515  /* nIndex is incremented each time a data packed */
1516  /* or unpacked in received. The size in bytes of */
1517  /* each data depends on the SPORT configuration. */
1518  /* In core driven operations, nCount represents */
1519  /* the number of 32-bit words transmitted. */
1520  /* In DMA driven operations, nCount represents */
1521  /* the number of DMA data transmitted */
1522  /* ============================================= */
1523  const uint32_t ctl = pRegs->CTL_A;
1524  const uint32_t bytesPerData = GetBytesPerSportData(ctl);
1525  const uint32_t nIndex = pBuff->nIndex * (4u / bytesPerData);
1526  assert((nIndex>=pBuff->nCount)||(true==pBuff->bDMA)); /* buffer must be fully processed */
1527  }
1528 #endif
1529 
1530  pBuff->bInUse = false; /* mark buffer as ready */
1531 
1532  NVIC_DisableIRQ(pSportInfo->eIRQn); /* suspend SPORT Interrupt */
1533  NVIC_DisableIRQ(pSportInfo->eDMAn); /* suspend SPORT DMA interrupt */
1534 
1535  pDevice->pSportInfo->eState = ADI_SPORT_STATE_PAUSED;
1536 
1537  if(NULL != pDevice->pfCallback) /* Call the callback function if one is registered. */
1538  {
1539  uint32_t evt = ( (ADI_SPORT_DIR_RX == pDevice->eDirection)
1542  );
1543 
1544  pDevice->pfCallback(pDevice->pCBParam,evt,pBuff->pStartAddress);
1545  pBuff->pStartAddress = NULL; /* No need to keep the processed buffer address */
1546  }
1547  else
1548  {
1549  SEM_POST(pSportChnl); /* signal the buffer availability through a semaphore */
1550  }
1551  pRegs->STAT_A = clrEvt; /* clear status register bits (W1C) */
1552  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONE; /* SPORT is available */
1553  pBuff = pBuff->pNextBuffer; /* point to the next buffer to process */
1554  pSportChnl->pFillBuffer = pBuff; /* this is the new pFillBuffer */
1555 
1556  if ((0u != pBuff->pStartAddress) && (true == pBuff->bInUse)) /* valid buffer not being processed yet */
1557  {
1558  ADI_SPORT_RESULT result;
1559 
1560  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONBLOCKING;
1561  if (true == pBuff->bDMA)
1562  {
1563  result = sport_SubmitBufferDmaMode(pDevice, pBuff);
1564  }
1565  else
1566  {
1567  result = sport_SubmitBufferIntMode(pDevice, pBuff);
1568  }
1569 
1570  if(ADI_SPORT_SUCCESS != result) /* if an error occurred...*/
1571  {
1572  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONE; /* SPORT is available */
1573  }
1574  }
1575 }
1576 
1577 /*
1578  * @brief Common SPORT interrupt handler function called by SPORT0 A and SPORT0 B ISRs.
1579  *
1580  * @details Process SPORT0 A and B interrupts, recording HW errors that must be reported,
1581  * reading/writing transmitted data, launching new SPORT transmissions if more
1582  * buffers are to be processed, and deactivating the SPORT device if there are
1583  * no pending requests. (Common fucntion for both core driven and DMA driven
1584  * SPORT operations.)
1585  *
1586  * @param [in] pDevice Sport device pointer related to the calling ISR.
1587  */
1588 static void sport_InterruptHandler(ADI_SPORT_DEVICE * pDevice)
1589 {
1590  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* get SPORT device information */
1591  volatile ADI_SPORT_TypeDef * pRegs = pSportInfo->pSportRegs; /* access SPORT registers */
1592  const uint32_t sportStatus = pRegs->STAT_A; /* read SPORT status */
1593  const uint32_t dataRequest = (sportStatus & BITM_SPORT_STAT_A_DATA);/* set if any data to be processed by the SPORT */
1594  const uint32_t hwEvents = sportStatus & recEvt; /* HW events to be recorded in the driver */
1595 
1596 
1597  /* This implementation assumes an identity mapping between BITM_SPORT_STAT values
1598  * and their equivalent event in ADI_SPORT_EVENT, e.g. ADI_SPORT_HW_ERR_FS and
1599  * BITM_SPORT_STAT_A_FSERR share the same value. This simplifies event processing
1600  * and reports. */
1601  assert(((uint32_t) ADI_SPORT_HW_ERR_RX_OVERFLOW) == BITM_SPORT_STAT_A_DERR);
1602  assert(((uint32_t) ADI_SPORT_HW_ERR_TX_UNDERFLOW) == BITM_SPORT_STAT_A_DERR);
1603  assert(((uint32_t) ADI_SPORT_HW_ERR_FS) == BITM_SPORT_STAT_A_FSERR);
1604  assert(((uint32_t) ADI_SPORT_HW_ERR_SYSDATAERR) == BITM_SPORT_STAT_A_SYSDATERR);
1605 
1606  if (0u != hwEvents) /* any event recorded? */
1607  {
1608  if (NULL != pDevice->pfCallback) /* if a callback has been registered ? */
1609  {
1610  pDevice->pfCallback(pDevice->pCBParam,hwEvents,NULL); /* then call it */
1611  } else {
1612  pDevice->nHwError |= hwEvents; /* else set the driver HW error */
1613  SEM_POST(&pDevice->sportChannel); /* and signal this through a semaphore */
1614  }
1615  }
1616 
1617  if (0u != dataRequest) /* Tx FIFO is not full or Rx FIFO is not empty */
1618  {
1619  ADI_DT_BUFF_INFO * pBuff = pDevice->sportChannel.pFillBuffer;
1620  uint32_t * pNextWord = (uint32_t*) pBuff->pStartAddress;
1621 
1622  if ((NULL != pNextWord) && (pBuff->nIndex < pBuff->nCount)) /* This buffer has not been fully processed yet */
1623  {
1624  if (ADI_SPORT_DIR_RX == pDevice->eDirection)
1625  {
1626  pNextWord[pBuff->nIndex++] = pRegs->RX_A; /* Read the data received in RX and increment the index */
1627  while (!DXS_FIFO_IS_EMPTY(pRegs->STAT_A)) /* and if there are more data available in the FIFO */
1628  {
1629  pNextWord[pBuff->nIndex++] = pRegs->RX_A; /* Read remaining data received in RX and increment the index */
1630  }
1631  }
1632  else
1633  {
1634  pRegs->TX_A = pNextWord[pBuff->nIndex++]; /* Write the data to be sent into TX and increment the index */
1635  while ( (pBuff->nIndex < pBuff->nCount) /* and if there are more data to be sent */
1636  && (!DXS_FIFO_IS_FULL(pRegs->STAT_A)) /* and there is still room in the FIFO */
1637  )
1638  {
1639  pRegs->TX_A = pNextWord[pBuff->nIndex++]; /* then write more data to be sent into TX and increment the index */
1640  }
1641  }
1642  }
1643  }
1644 
1645  /* ========================================================== */
1646  /* Common to core driven operations and DMA driven operations */
1647  /* ========================================================== */
1648  if (0u != (pRegs->STAT_A & BITM_SPORT_STAT_A_TFI)) /* If a SPORT Tx/Rx request has finished */
1649  {
1650  sport_Terminate(pDevice);
1651  }
1652 
1653 #if defined(ADI_CYCLECOUNT_SPORT_ISR_ENABLED) && (ADI_CYCLECOUNT_SPORT_ISR_ENABLED == 1u)
1655 #endif
1656 }
1657 
1659 void SPORT0A_Int_Handler(void)
1660 {
1661  ISR_PROLOG();
1662  sport_InterruptHandler(gSportDevInfo[0][ADI_HALF_SPORT_A].hDevice);
1663  ISR_EPILOG();
1664 }
1665 
1667 void SPORT0B_Int_Handler(void)
1668 {
1669  ISR_PROLOG();
1670  sport_InterruptHandler(gSportDevInfo[0][ADI_HALF_SPORT_B].hDevice);
1671  ISR_EPILOG();
1672 }
1673 
1674 void DMA_SPORT0A_Int_Handler(void)
1675 {
1676  ISR_PROLOG();
1682  sport_Terminate(gSportDevInfo[0][ADI_HALF_SPORT_A].hDevice);
1683 #if defined(ADI_CYCLECOUNT_SPORT_ISR_ENABLED) && (ADI_CYCLECOUNT_SPORT_ISR_ENABLED == 1u)
1685 #endif
1686  ISR_EPILOG();
1687 }
1688 
1689 void DMA_SPORT0B_Int_Handler(void)
1690 {
1691  ISR_PROLOG();
1697  sport_Terminate(gSportDevInfo[0][ADI_HALF_SPORT_B].hDevice);
1698 #if defined(ADI_CYCLECOUNT_SPORT_ISR_ENABLED) && (ADI_CYCLECOUNT_SPORT_ISR_ENABLED == 1u)
1700 #endif
1701  ISR_EPILOG();
1702 }
1703 
1704 static void sport_DmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg)
1705 {
1706  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) pCBParam; /* Recover the device handle. */
1707  ADI_DT_BUFF_INFO * pFillBuffer = pDevice->sportChannel.pFillBuffer;
1708  ADI_DT_BUFF_INFO * pNextBuffer = pFillBuffer->pNextBuffer;
1709  uint32_t nEvent = 0u;
1710 
1711  if (ADI_DMA_EVENT_ERR_BUS == Event)
1712  {
1713  nEvent = (uint32_t) ADI_SPORT_DMA_ERR_BUS; /* SPORT DMA bus error detected */
1714  } else {
1715  assert(ADI_DMA_EVENT_ERR_INVALID_DESCRIPTOR == Event);
1716  nEvent = (uint32_t) ADI_SPORT_DMA_ERR_INVALID_DESCRIPTOR; /* SPORT DMA invalid descriptor error detected */
1717  }
1718 
1719  pDevice->nHwError |= nEvent;
1720  sport_InterruptHandler(pDevice);
1721 
1722  while ( (NULL != pNextBuffer->pStartAddress)
1723  && (true == pNextBuffer->bInUse)
1724  && (true == pNextBuffer->bDMA)
1725  ) /* another buffer is pending for a DMA driven request */
1726  {
1727  pDevice->nHwError |= nEvent;
1728  pNextBuffer->bInUse = false;
1729  sport_InterruptHandler(pDevice);
1730  pNextBuffer = pNextBuffer->pNextBuffer;
1731  }
1732 }
1733 
1734 static inline uint32_t GetBytesPerSportData(const uint32_t ctlVal)
1735 {
1736  const uint32_t wlen = SPORT_GET_WLEN(ctlVal);
1737  const uint32_t bytesPerData = ((wlen < 9u) ? (1u) : ((wlen < 17u) ? (2u) : (4u)));
1738  return bytesPerData;
1739 }
1740 
ADI_DMA_RESULT adi_dma_RegisterCallback(DMA_CHANn_TypeDef const eChannelID, ADI_CALLBACK const pfCallback, void *const pCBParam)
Register a call-back function for a DMA channel.
Definition: adi_dma.c:232
#define ADI_CFG_SPORT0A_CONVT_POLARITY
#define ADI_CFG_SPORT0A_FS_REQUIRED
#define ADI_CFG_SPORT0B_LSB_FIRST
#define ADI_CYCLECOUNT_STORE(id)
#define ADI_CFG_SPORT0A_DATA_INDEPENDENT_FS
#define ADI_CFG_SPORT0A_FS_ERROR_OPERATION
#define ADI_CFG_SPORT0A_INTERNAL_CLK
#define ADI_CFG_SPORT0B_ACTIVE_LOW_FS
ADI_SPORT_DIRECTION
Definition: adi_sport.h:56
#define ADI_CFG_SPORT0B_SERIAL_WLEN
#define ADI_CFG_SPORT0B_LATE_FS
void SPORT0A_Int_Handler(void)
#define ADI_CFG_SPORT0B_CONVT_WIDTH
#define ADI_CFG_SPORT0B_CLOCK_EDGE
#define ADI_CFG_SPORT0B_GATED_CLOCK
#define ADI_CFG_SPORT0A_INTERNAL_FS
void SPORT0B_Int_Handler(void)
ADI_SPORT_RESULT adi_sport_MultiplexSportSignal(ADI_SPORT_HANDLE const hDevice, const bool bUseOtherFS, const bool bUseOtherClk)
Configure the SPORT use the Clocks and Frame Sync of other Half-Sport.
Definition: adi_sport.c:1258
#define ADI_CFG_SPORT0B_INTERNAL_CLK
void * ADI_SPORT_HANDLE
Definition: adi_sport.h:42
#define ADI_CFG_SPORT0B_FS_DIVISOR
ADI_SPORT_CHANNEL
Definition: adi_sport.h:47
ADI_SPORT_RESULT adi_sport_ConfigData(ADI_SPORT_HANDLE const hDevice, const uint8_t nWordLength, const ADI_SPORT_PACKING_MODE ePackMode, const bool bLSBFirst)
Sets data format for the specified SPORT device.
Definition: adi_sport.c:899
void DMA_SPORT0B_Int_Handler(void)
#define ADI_CFG_SPORT0B_CLOCK_DIVISOR
#define ADI_CFG_SPORT0A_ACTIVE_LOW_FS
ADI_SPORT_RESULT adi_sport_SubmitBuffer(ADI_SPORT_HANDLE const hDevice, void *const pBuffer, uint32_t const nNumBytes, bool const bDMA)
Submit the buffer for transmitting/receiving the data. This function can be used to submit the buffer...
Definition: adi_sport.c:348
ADI_SPORT_RESULT adi_sport_ConfigTimerMode(ADI_SPORT_HANDLE const hDevice, const uint8_t nFSDuration, const uint8_t nWidth, const bool bActiveLow)
Configure the SPORT use the Clocks and Frame Sync of other Half-Sport.
Definition: adi_sport.c:1322
#define ADI_CFG_SPORT0B_ENABLE_PACKING
void DMA_SPORT0A_Int_Handler(void)
ADI_SPORT_RESULT adi_sport_Close(ADI_SPORT_HANDLE const hDevice)
Closes the operation of specified SPORT device.
Definition: adi_sport.c:293
ADI_SPORT_RESULT adi_sport_ConfigClock(ADI_SPORT_HANDLE const hDevice, const uint16_t nClockRatio, const bool bUseIntlClock, const bool bRisingEdge, const bool bGatedClk)
Configure the clock for the specified SPORT device.
Definition: adi_sport.c:1031
ADI_SPORT_RESULT adi_sport_IsBufferAvailable(ADI_SPORT_HANDLE const hDevice, bool *const pbAvailable)
Peek function to know whether an empty/filled buffer is available. Call to this function is valid onl...
Definition: adi_sport.c:778
#define ADI_CYCLECOUNT_ISR_SPORT
ADI_SPORT_PACKING_MODE
Definition: adi_sport.h:65
#define ADI_CFG_SPORT0A_OPERATION_MODE
#define ADI_CFG_SPORT0A_LATE_FS
ADI_SPORT_RESULT adi_sport_Open(const uint32_t nDevNum, const ADI_SPORT_CHANNEL eChannel, const ADI_SPORT_DIRECTION eDirection, void *pMemory, const uint32_t nMemSize, ADI_SPORT_HANDLE *const phDevice)
Initialization function for SPORT device.
Definition: adi_sport.c:193
#define ADI_CFG_SPORT0B_OPERATION_MODE
#define ADI_CFG_SPORT0A_ENABLE_FSMUXSEL
#define ADI_CFG_SPORT0A_FS_DIVISOR
#define ADI_CFG_SPORT0A_CONVT_WIDTH
#define ADI_CFG_SPORT0B_CONVT_FS_DURATION
#define ADI_CFG_SPORT0A_CLOCK_EDGE
#define ADI_CFG_SPORT0B_INTERNAL_FS
#define ADI_CFG_SPORT0A_CLOCK_DIVISOR
#define ADI_CFG_SPORT0B_FS_ERROR_OPERATION
#define ADI_CFG_SPORT0A_LSB_FIRST
void adi_dma_Init(void)
Initialize the DMA peripheral.
Definition: adi_dma.c:155
#define ADI_CFG_SPORT0B_CONVT_POLARITY
ADI_SPORT_RESULT
Definition: adi_sport.h:94
#define ADI_CFG_SPORT0A_ENABLE_PACKING
ADI_SPORT_RESULT adi_sport_RegisterCallback(ADI_SPORT_HANDLE const hDevice, const ADI_CALLBACK pfCallback, void *const pCBparam)
Register and unregister a Callback function with the SPORT device driver. A registered call back func...
Definition: adi_sport.c:836
ADI_SPORT_RESULT adi_sport_GetBuffer(ADI_SPORT_HANDLE const hDevice, void **const ppBuffer, uint32_t *pHwError)
This function returns the address of a processed buffer. This is a blocking function: it waits until ...
Definition: adi_sport.c:717
#define ADI_CFG_SPORT0A_CONVT_FS_DURATION
ADI_SPORT_RESULT adi_sport_ConfigFrameSync(ADI_SPORT_HANDLE const hDevice, const uint16_t nFsDivisor, const bool bFSRequired, const bool bInternalFS, const bool bDataFS, const bool bActiveLowFS, const bool bLateFS, const bool bFSErrorOperation)
Frame Sync(FS) configuration for the specified SPORT.
Definition: adi_sport.c:1162
#define ADI_CFG_SPORT0A_SERIAL_WLEN
#define ADI_CFG_SPORT0B_FS_REQUIRED
#define ADI_CFG_SPORT0B_DATA_INDEPENDENT_FS
#define ADI_SPORT_MEMORY_SIZE
Definition: adi_sport.h:40
#define ADI_CFG_SPORT0A_GATED_CLOCK
#define ADI_CFG_SPORT0A_ENABLE_CKMUXSEL