ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_sport.c
1 
54 /*============= I N C L U D E S =============*/
55 
56 #include <assert.h>
57 #include <string.h> /* memset declaration */
58 
59 #include <drivers/general/adi_drivers_general.h>
60 #include <adi_sport_config.h>
61 #include <drivers/sport/adi_sport.h>
62 #include <adi_cyclecount.h>
63 #include "adi_sport_def.h"
64 
65 #ifdef __ICCARM__
66 /*
67 * IAR MISRA C 2004 error suppressions.
68 *
69 * Pm123 (rule 8.5): there shall be no definition of objects or functions in a header file
70 * This isn't a header as such.
71 *
72 * Pm073 (rule 14.7): a function should have a single point of exit
73 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
74 * Multiple returns are used for error handling.
75 *
76 * Pm050 (rule 14.2): a null statement shall only occur on a line by itself
77 * Needed for null expansion of ADI_INSTALL_HANDLER and others.
78 *
79 * Pm088 (rule 17.4): pointer arithmetic should not be used.
80 * Relying on pointer arithmetic for buffer handling.
81 *
82 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
83 * The rule makes an exception for memory-mapped register accesses.
84 *
85 * Pm152: (MISRA C 2004 rule 17.4) array indexing shall only be applied to objects defined as an array type
86 * Accessing the DMA descriptors, which are defined in the system as a pointer to an array of descriptors
87 
88 */
89 #pragma diag_suppress=Pm026,Pm050,Pm073,Pm088,Pm123,Pm140,Pm143,Pm152,Pm153
90 #endif /* __ICCARM__ */
91 
92 /*============== D A T A ===============*/
93 
94 #define SPORT0_A_REGS ((volatile ADI_SPORT_TypeDef*)REG_SPORT0_CTL_A)
95 #define SPORT0_B_REGS ((volatile ADI_SPORT_TypeDef*)REG_SPORT0_CTL_B)
96 
97 #define SPORT0_A_CFG { 0u, 0u, 0u, 0u, 0u }
98 #define SPORT0_B_CFG { 0u, 0u, 0u, 0u, 0u }
99 
100 #define DXS_FIFO_IS_FULL(STAT) (((STAT) & BITM_SPORT_STAT_A_DXS) == BITM_SPORT_STAT_A_DXS)
101 #define DXS_FIFO_IS_EMPTY(STAT) (((STAT) & BITM_SPORT_STAT_A_DXS) == 0u)
102 
103 static ADI_SPORT_DEVICE_INFO gSportDevInfo [ADI_SPORT_NUM_INSTANCES][ADI_SPORT_NUM_CHANNELS] =
104 {
105  {/* registers configuration initial state DMA channel DMA IRQ SPORT IRQ handle */
106  {SPORT0_A_REGS, SPORT0_A_CFG, ADI_SPORT_STATE_UNINITIALIZED, SPORT0A_CHANn, DMA0_CH2_DONE_IRQn, SPORT_A_EVT_IRQn, NULL},
107  {SPORT0_B_REGS, SPORT0_B_CFG, ADI_SPORT_STATE_UNINITIALIZED, SPORT0B_CHANn, DMA0_CH3_DONE_IRQn, SPORT_B_EVT_IRQn, NULL},
108  },
109 };
110 
111 
112 static const ADI_SPORT_CONFIG gSportCfg[ADI_SPORT_NUM_INSTANCES][ADI_SPORT_NUM_CHANNELS] =
113 {
114  { /* configuration for SPORT 0 */
115  /* Configuration for half-SPORT A */
116  { /* SPORT_CTL register */
117  ((ADI_CFG_SPORT0A_ENABLE_FSMUXSEL) << BITP_SPORT_CTL_A_FSMUXSEL) |
118  ((ADI_CFG_SPORT0A_ENABLE_CKMUXSEL) << BITP_SPORT_CTL_A_CKMUXSEL) |
119  ((ADI_CFG_SPORT0A_LSB_FIRST) << BITP_SPORT_CTL_A_LSBF) |
120  ((ADI_CFG_SPORT0A_SERIAL_WLEN - 1u) << BITP_SPORT_CTL_A_SLEN) |
121  ((ADI_CFG_SPORT0A_INTERNAL_CLK) << BITP_SPORT_CTL_A_ICLK) |
122  ((ADI_CFG_SPORT0A_OPERATION_MODE) << BITP_SPORT_CTL_A_OPMODE) |
123  ((ADI_CFG_SPORT0A_CLOCK_EDGE) << BITP_SPORT_CTL_A_CKRE) |
124  ((ADI_CFG_SPORT0A_FS_REQUIRED) << BITP_SPORT_CTL_A_FSR) |
125  ((ADI_CFG_SPORT0A_INTERNAL_FS) << BITP_SPORT_CTL_A_IFS) |
126  ((ADI_CFG_SPORT0A_DATA_INDEPENDENT_FS) << BITP_SPORT_CTL_A_DIFS) |
127  ((ADI_CFG_SPORT0A_ACTIVE_LOW_FS) << BITP_SPORT_CTL_A_LFS) |
128  ((ADI_CFG_SPORT0A_LATE_FS) << BITP_SPORT_CTL_A_LAFS) |
129  ((ADI_CFG_SPORT0A_ENABLE_PACKING) << BITP_SPORT_CTL_A_PACK) |
130  ((ADI_CFG_SPORT0A_FS_ERROR_OPERATION) << BITP_SPORT_CTL_A_FSERRMODE) |
131  ((ADI_CFG_SPORT0A_GATED_CLOCK) << BITP_SPORT_CTL_A_GCLKEN),
132 
133  /* SPORT_DIV register */
134  ((ADI_CFG_SPORT0A_CLOCK_DIVISOR) << BITP_SPORT_DIV_A_CLKDIV) |
135  ((ADI_CFG_SPORT0A_FS_DIVISOR) << BITP_SPORT_DIV_A_FSDIV),
136 
137  /* SPORT_CONVT register */
138  ((ADI_CFG_SPORT0A_CONVT_WIDTH) << BITP_SPORT_CNVT_A_WID) |
139  ((ADI_CFG_SPORT0A_CONVT_POLARITY) << BITP_SPORT_CNVT_A_POL) |
140  ((ADI_CFG_SPORT0A_CONVT_FS_DURATION) << BITP_SPORT_CNVT_A_CNVT2FS),
141 
142  /* Default DMA data size for SPORT */
144 
145  /* Default DMA data increment for SPORT */
147  },
148 
149  /* Configuration for half-SPORT B */
150  { /* SPORT_CTL register */
151  ((ADI_CFG_SPORT0B_LSB_FIRST) << BITP_SPORT_CTL_B_LSBF) |
152  ((ADI_CFG_SPORT0B_SERIAL_WLEN - 1u) << BITP_SPORT_CTL_B_SLEN) |
153  ((ADI_CFG_SPORT0B_INTERNAL_CLK) << BITP_SPORT_CTL_B_ICLK) |
154  ((ADI_CFG_SPORT0B_OPERATION_MODE) << BITP_SPORT_CTL_B_OPMODE) |
155  ((ADI_CFG_SPORT0B_CLOCK_EDGE) << BITP_SPORT_CTL_B_CKRE) |
156  ((ADI_CFG_SPORT0B_FS_REQUIRED) << BITP_SPORT_CTL_B_FSR) |
157  ((ADI_CFG_SPORT0B_INTERNAL_FS) << BITP_SPORT_CTL_B_IFS) |
158  ((ADI_CFG_SPORT0B_DATA_INDEPENDENT_FS) << BITP_SPORT_CTL_B_DIFS) |
159  ((ADI_CFG_SPORT0B_ACTIVE_LOW_FS) << BITP_SPORT_CTL_B_LFS) |
160  ((ADI_CFG_SPORT0B_LATE_FS) << BITP_SPORT_CTL_B_LAFS) |
161  ((ADI_CFG_SPORT0B_ENABLE_PACKING) << BITP_SPORT_CTL_B_PACK) |
162  ((ADI_CFG_SPORT0B_FS_ERROR_OPERATION) << BITP_SPORT_CTL_B_FSERRMODE) |
163  ((ADI_CFG_SPORT0B_GATED_CLOCK) << BITP_SPORT_CTL_B_GCLKEN),
164 
165  /* SPORT_DIV register */
166  ((ADI_CFG_SPORT0B_CLOCK_DIVISOR) << BITP_SPORT_DIV_B_CLKDIV) |
167  ((ADI_CFG_SPORT0B_FS_DIVISOR) << BITP_SPORT_DIV_B_FSDIV),
168 
169  /* SPORT_CONVT register */
170  ((ADI_CFG_SPORT0B_CONVT_WIDTH) << BITP_SPORT_CNVT_B_WID) |
171  ((ADI_CFG_SPORT0B_CONVT_POLARITY) << BITP_SPORT_CNVT_B_POL) |
172  ((ADI_CFG_SPORT0B_CONVT_FS_DURATION) << BITP_SPORT_CNVT_B_CNVT2FS),
173 
174  /* Default DMA data size for SPORT */
176 
177  /* Default DMA data increment for SPORT */
178  ADI_DMA_INCR_4_BYTE
179  }
180  }
181 };
182 
185 /*============= C O D E =============*/
186 
187 extern void SPORT0A_Int_Handler(void);
188 extern void SPORT0B_Int_Handler(void);
189 extern void DMA_SPORT0A_Int_Handler(void);
190 extern void DMA_SPORT0B_Int_Handler(void);
192 /*============= L O C A L F U N C T I O N S =============*/
193 
194 /*============= P U B L I C F U N C T I O N S =============*/
195 
225  const uint32_t nDevNum,
226  const ADI_SPORT_CHANNEL eChannel,
227  const ADI_SPORT_DIRECTION eDirection,
228  void *pMemory,
229  const uint32_t nMemSize,
230  ADI_SPORT_HANDLE * const phDevice
231  )
232 {
234 
235  assert(ADI_SPORT_MEMORY_SIZE == sizeof(ADI_SPORT_DEVICE)); /* validate the memory size macro */
236 #ifdef ADI_DEBUG
237  if (nDevNum >= ADI_SPORT_NUM_INSTANCES)
238  {
239  result = ADI_SPORT_INVALID_DEVICE_NUM; /* SPORT identifier must be within [0..ADI_SPORT_NUM_INSTANCES-1] */
240  }
241  else if (phDevice == NULL)
242  {
243  result = ADI_SPORT_INVALID_NULL_POINTER; /* the pointer to device handle must be valid */
244  }
245  else if (ADI_SPORT_MEMORY_SIZE != nMemSize)
246  {
247  result = ADI_SPORT_FAILED;
248  }
249  else if (ADI_SPORT_STATE_UNINITIALIZED != gSportDevInfo[nDevNum][eChannel].eState)
250  {
251  result = ADI_SPORT_DEVICE_IN_USE; /* the device instance must not be in use */
252  }
253  else
254 #endif /* ADI_DEBUG */
255  {
256  ADI_SPORT_DEVICE * pDevice = pMemory; /* Pointer to the SPORT device instance (from supplied memory) */
257  ADI_SPORT_DEVICE_INFO * sportInfo = &gSportDevInfo[nDevNum][eChannel]; /* SPORT info for HSPORT A or HSPORT B */
258  ADI_SPORT_CONFIG const * sportCfg = &gSportCfg[nDevNum][eChannel]; /* SPORT configuration for HSPORT A or HSPORT B */
259 
260  assert(eChannel < ADI_SPORT_NUM_CHANNELS);
261 
262  memset(pMemory, 0, nMemSize); /* clear the device instance data before initializing it */
263 
264  pDevice->pSportInfo = sportInfo; /* Initialize the pointer which provides the device information (HSPORT A or HSPORT B). */
265  pDevice->eDirection = eDirection; /* Initialize the direction (BEFORE calling sport_Configure)*/
266  pDevice->nHwError = (uint32_t) ADI_SPORT_HW_NO_ERR;
267 
268  adi_dma_Init(); /* Set up the DMA Controller. */
269  sport_Init(pDevice); /* Initialize the data transmission buffers */
270  sport_Configure(pDevice,sportCfg); /* Configure the SPORT */
271 
272  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(sportInfo->eDMAChnlID, sport_DmaErrorCallback, pDevice))
273  {
274  adi_sport_Close(pDevice);
276  }
277 
278  if (ADI_SPORT_SUCCESS == result)
279  {
280  ADI_SPORT_DEVICE_INFO * devInfo = &gSportDevInfo[nDevNum][eChannel];
281 
282  /* Create a "semaphore" (varies per OS) used for blocking buffer resource management. */
283  if (ADI_HALF_SPORT_A == eChannel)
284  {
285  SEM_CREATE(&pDevice->sportChannel, "SPORT0_A_SEM", ADI_SPORT_FAILED);
286  }else{
287  SEM_CREATE(&pDevice->sportChannel, "SPORT0_B_SEM", ADI_SPORT_FAILED);
288  }
289 
290  /* Change the state of the specified device */
291  ADI_INT_STATUS_ALLOC();
292  ADI_ENTER_CRITICAL_REGION();
293  devInfo->eState = ADI_SPORT_STATE_INITIALIZED;
294  devInfo->hDevice = pDevice;
295  ADI_EXIT_CRITICAL_REGION();
296  *phDevice = pDevice; /* Return the device handle to the application */
297  }
298  }
299 
300  return result;
301 }
302 
325 {
326  ADI_SPORT_RESULT result = ADI_SPORT_SUCCESS; /* return code */
327  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
328 #ifdef ADI_DEBUG
329  if (ADI_SPORT_SUCCESS == (result=ValidateHandle(pDevice))) /* Validate the given handle */
330 #endif /* ADI_DEBUG */
331  {
332  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo;
333 
334  /* Free up the device */
335  ADI_INT_STATUS_ALLOC();
336  ADI_ENTER_CRITICAL_REGION();
337  NVIC_DisableIRQ(pSportInfo->eIRQn); /* Disable SPORT event interrupts. */
338  NVIC_DisableIRQ(pSportInfo->eDMAn); /* Disable DMA SPORT interrupts. */
339  pSportInfo->eState = ADI_SPORT_STATE_UNINITIALIZED;
340  pSportInfo->hDevice = NULL; /* Free up the device memory. */
341  ADI_EXIT_CRITICAL_REGION();
342 
343  SEM_DELETE(&pDevice->sportChannel, ADI_SPORT_FAILED); /* Delete SPORT channel semaphore. */
344 
345  adi_dma_RegisterCallback(pSportInfo->eDMAChnlID, NULL, NULL); /* unregister the callback function in the DMA error handler */
346 
347  pSportInfo->pSportRegs->CTL_A = 0u;
348  }
349  return result;
350 }
351 
380  void * const pBuffer,
381  uint32_t const nNumBytes,
382  bool const bDMA
383  )
384 {
385  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* pointer to SPORT device instance */
386  ADI_SPORT_RESULT result = ADI_SPORT_SUCCESS; /* return code */
387 
388 #ifdef ADI_DEBUG
389  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg; /* short cut to SPORT configuration */
390 
391  if(ADI_SPORT_SUCCESS != (result=ValidateHandle(hDevice))) /* validate the given handle */
392  {
393  }
394  else if ( ((2u >= nNumBytes) && ((pDevice->pSportInfo->pSportRegs->CTL_A & BITM_SPORT_CTL_A_OPMODE) != 0u))
395  || (0u != (nNumBytes & ~(BITM_SPORT_NUMTRAN_A_VALUE))) /* buffer size limited by SPORT transmission capabilities */
396  )
397  {
399  }
400  else
401 #endif /* ADI_DEBUG */
402  /* Check that there is a free buffer to use for this transmit operation. pFreeBuffer
403  is the next buffer available, so if it is in use we can make the assumption that
404  there are no buffers available. The start address is set to NULL once the buffer
405  has finished being processed in "adi_sport_GetBuffer()".
406  */
407  if (NULL != pDevice->sportChannel.pFreeBuffer->pStartAddress)
408  {
410  }
411  else
412  {
413 #ifdef ADI_DEBUG
414  const uint32_t addr = (uint32_t) pBuffer;
415 
416  if (true == bDMA)
417  {
427  const uint32_t dataSizeInBytes = GetBytesPerSportData(pSportCfg->CTL);
428  const uint32_t full = nNumBytes / dataSizeInBytes; /* number of full data to transmit/receive */
429  const uint32_t partial = nNumBytes % dataSizeInBytes; /* number of partial data to transmit/receive */
430  const uint32_t misaligned = addr % dataSizeInBytes; /* number of data to transmit/receive */
431 
432  if ( (full > DMA_TRANSFER_LIMIT) /* number of data to process too large for DMA */
433  || (0u != partial) /* buffer size not a multiple of dataSizeInBytes */
434  || (0u != misaligned) /* buffer mis-aligned */
435  )
436  {
438  }
439  } else {
440  const uint32_t misAligned = addr % 4u;
441  const uint32_t invalidNum = nNumBytes % 4u;
442 
443  if ( (0u != misAligned) /* mis-aligned buffer */
444  || (0u != invalidNum) /* number of bytes not a multiple of 32-bit */
445  )
446  {
447  result = ADI_SPORT_INVALID_PARAMETER; /* reject the buffer submission */
448  }
449  }
450  if (ADI_SPORT_SUCCESS == result)
451 #endif /* ADI_DEBUG */
452  {
453  ADI_DT_CHANNEL * pSportChnl = &pDevice->sportChannel;
454 
455  pSportChnl->pFreeBuffer->pStartAddress = pBuffer; /* Set the start address of the data buffer */
456  pSportChnl->pFreeBuffer->nCount = nNumBytes; /* Set the buffer size */
457  pSportChnl->pFreeBuffer->nIndex = 0u; /* Initialize the buffer index to zero (1st data in buffer) */
458  pSportChnl->pFreeBuffer->bDMA = bDMA; /* Set the DMA boolean value. */
459  pSportChnl->pFreeBuffer->bInUse = true; /* this buffer is now being used by the SPORT */
460 
461  /* Now that this "pFreeBuffer" is no longer free for use, update the
462  "pFreeBuffer" to the next buffer. "pFreeBuffer" will only be updated
463  during the process of submitting a buffer or a read/write operation.
464  */
465  pSportChnl->pFreeBuffer = pSportChnl->pFreeBuffer->pNextBuffer;
466 
467  /* Set the data transfer mode in case it was #ADI_DT_MODE_NONE. This
468  will be set back to #ADI_DT_MODE_NONE once this transaction is complete.
469  Then, if a buffer is not currently active, set up the interrupts for
470  this transaction. Otherwise if a buffer is currently active, this will
471  be taken care of in the ISR.
472  */
473  if (pSportChnl->eDataTranferMode == ADI_DT_MODE_NONE) /* if the SPORT is available for a transmission */
474  {
475  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONBLOCKING;
476 
477  /* call an appropriate function based on mode in which device is operating */
478  if (true == bDMA) /* select a DMA driven or a core driven non-blocking transmission */
479  {
480  result = sport_SubmitBufferDmaMode(pDevice, pSportChnl->pFillBuffer);
481  } else {
482  result = sport_SubmitBufferIntMode(pDevice, pSportChnl->pFillBuffer);
483  }
484  }
485 
486  if(ADI_SPORT_SUCCESS != result) /* if an error occurred...*/
487  {
488  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONE; /* SPORT is available */
489  }
490  }
491  }
492 
493  return result;
494 }
495 
496 /*
497  * @brief Submit a buffer for SPORT Rx or Tx DMA driven transmission.
498  *
499  * @param [in] pDevice Pointer to SPORT device.
500  *
501  * @param [in] pBuffer Pointer to data transfer buffer information.
502  *
503  * @return Status
504  *
505  * - #ADI_SPORT_SUCCESS buffer successfully submitted to the DMA associated with the SPORT.
506  * - #ADI_SPORT_BUFFERS_NOT_SUBMITTED Failed to submit the buffer to the DMA associated with the SPORT.
507  */
509 static ADI_SPORT_RESULT sport_SubmitBufferDmaMode(ADI_SPORT_DEVICE * pDevice,
510  ADI_DT_BUFF_INFO * pBuff)
511 {
513  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* short cut to SPORT information */
514  ADI_SPORT_CONFIG * pSportCfg = &pSportInfo->sportCfg; /* short cut to SPORT configuration */
515 
516 #ifdef ADI_DEBUG
517  if ( (pBuff != pDevice->sportChannel.pFillBuffer) /* a submitted buffer should always be the current fill buffer */
518  || (true != pBuff->bInUse) /* Processed buffers should already be marked as being used */
519  || (0u != pBuff->nIndex) /* processing should start from index 0 */
520  )
521  {
522  result = ADI_SPORT_FAILED;
523  }
524  else
525 #endif
526  {
527  volatile ADI_SPORT_TypeDef* pSportRegs = pSportInfo->pSportRegs;/* short cut to SPORT registers */
528  const uint32_t dmaChnlId = (uint32_t) pSportInfo->eDMAChnlID; /* identifier for the DMA channel to be used */
529  const uint32_t dmaChnlBit = (1u << dmaChnlId); /* bit representing the DMA channel to be used */
530 
541  const uint32_t dmaIncNone = (uint32_t) ADI_DMA_INCR_NONE;
542  const uint32_t dmaDcc = (uint32_t) DMA_ENUM_CTL_CYCLE_CTL_BASIC;
543  const uint32_t bytesPerData = GetBytesPerSportData(pSportCfg->CTL);
544 
545  const uint32_t dataSizeInBytes = (1u << pSportCfg->DMA_WIDTH); /* number of bytes in each data to transmit/receive */
546  uint32_t numDmaData = pBuff->nCount / dataSizeInBytes; /* number of DMA data to transmit/receive */
547  const uint32_t dmaDataEnd = (pBuff->nCount - dataSizeInBytes); /* position of last <8,16,32>-bit data in the DMA transfer being setup */
548  const uint32_t startAddress = (uint32_t) pBuff->pStartAddress; /* address of the first byte in the data buffer */
549  const uint32_t numSportData = pBuff->nCount / bytesPerData; /* number of SPORT data to transmit/receive */
550 
551  assert(pBuff->nCount == (numSportData * bytesPerData));
552  assert(numSportData <= 0xFFFu);
553  assert(0u == (pBuff->nCount % dataSizeInBytes));
554  assert(numDmaData <= DMA_TRANSFER_LIMIT);
555  assert((ADI_SPORT_DIR_RX == pDevice->eDirection) || (ADI_SPORT_DIR_TX == pDevice->eDirection));
556  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
557 
558  pSportRegs->CTL_A = 0u; /* make sure SPORT is disable */
559  pADI_DMA0->SRCADDR_CLR = dmaChnlBit; /* Clear source address decrement for TX channel DMA. */
560  pADI_DMA0->EN_SET = dmaChnlBit; /* Enable channel DMA. */
561  pADI_DMA0->RMSK_CLR = dmaChnlBit; /* Enable SPORT peripheral to generate DMA requests. */
562  pADI_DMA0->ALT_CLR = dmaChnlBit; /* Set the primary control data structure as the current DMA descriptor. */
563  pADI_DMA0->PRI_SET = dmaChnlBit;
564 
565  if (ADI_SPORT_DIR_RX == pDevice->eDirection)
566  {
567  pPrimaryCCD[dmaChnlId].DMASRCEND = (uint32_t) &pSportRegs->RX_A; /* address of the last src data in the DMA transfer being setup */
568  pPrimaryCCD[dmaChnlId].DMADSTEND = startAddress + dmaDataEnd; /* address of the last dst data in the DMA transfer being setup */
569  pPrimaryCCD[dmaChnlId].DMACDC =
570  (pSportCfg->DMA_INC << ((uint32_t)DMA_BITP_CTL_DST_INC)) | /* destination address incremented by N bytes */
571  (dmaIncNone << ((uint32_t)DMA_BITP_CTL_SRC_INC)); /* source address not incremented */
572  }
573  else /* ADI_SPORT_DIR_TX */
574  {
575  pPrimaryCCD[dmaChnlId].DMASRCEND = startAddress + dmaDataEnd; /* address of the last src data in the DMA transfer being setup */
576  pPrimaryCCD[dmaChnlId].DMADSTEND = (uint32_t) &pSportRegs->TX_A; /* address of the last dst data in the DMA transfer being setup */
577  pPrimaryCCD[dmaChnlId].DMACDC =
578  (dmaIncNone << ((uint32_t)DMA_BITP_CTL_DST_INC)) | /* destination address not incremented */
579  (pSportCfg->DMA_INC << ((uint32_t)DMA_BITP_CTL_SRC_INC)); /* source address incremented by N byte */
580 
584  if (numDmaData < numSportData)
585  {
586  pPrimaryCCD[dmaChnlId].DMASRCEND = startAddress + dmaDataEnd + dataSizeInBytes; /* address of the last src data in the DMA transfer being setup */
587  numDmaData++;
588  }
589  }
590  pPrimaryCCD[dmaChnlId].DMACDC |=
591  (pSportCfg->DMA_WIDTH << ((uint32_t)DMA_BITP_CTL_SRC_SIZE)) | /* source data size in bytes */
592  (0u << ((uint32_t) DMA_BITP_CTL_R_POWER)) |
593  ((numDmaData - 1u) << ((uint32_t)DMA_BITP_CTL_N_MINUS_1)) | /* number of DMA transfers (minus 1) */
594  (dmaDcc << ((uint32_t)DMA_BITP_CTL_CYCLE_CTL));
595 
596  ADI_INT_STATUS_ALLOC();
597  ADI_ENTER_CRITICAL_REGION();
598  pDevice->pSportInfo->eState = ADI_SPORT_STATE_DATA_FLOW_ENABLED;
599  pSportRegs->NUMTRAN_A = numSportData;
600 
601  /* Enable SPORT DMA request interrupt for the SPORT tx channel. */
602  NVIC_ClearPendingIRQ(pSportInfo->eIRQn);
603  NVIC_ClearPendingIRQ(pSportInfo->eDMAn);
604 
605  uint32_t ien_a = ((uint32_t)BITM_SPORT_IEN_A_SYSDATERR) |
606  ((uint32_t)BITM_SPORT_IEN_A_FSERRMSK) |
607  ((uint32_t)BITM_SPORT_IEN_A_DERRMSK);
608  if (ADI_SPORT_DIR_RX == pDevice->eDirection)
609  {
610  /* Allow SPORT DMA interrupt handling to mark SPORT Rx as complete */
611  NVIC_EnableIRQ(pSportInfo->eDMAn);
612  }
613  else
614  {
615  /* SPORT DMA Tx is complete when TFI is raised: enable TFI */
616  ien_a |= ((uint32_t)BITM_SPORT_IEN_A_TF);
617  }
618 
619  NVIC_EnableIRQ(pSportInfo->eIRQn);
620 
621  pSportRegs->IEN_A = ien_a;
622  pSportRegs->CTL_A = pSportCfg->CTL |
623  ((uint32_t)BITM_SPORT_CTL_A_SPEN) |
624  ((uint32_t)BITM_SPORT_CTL_A_DMAEN);
625  ADI_EXIT_CRITICAL_REGION();
626 
627  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
628  }
629  return result;
630 }
631 
633 /*
634  * @brief Submit a buffer for SPORT Rx or Tx core driven transmission.
635  *
636  * @details Submit a buffer for SPORT Rx or Tx core driven transmission.
637  * The buffer must be 32-bit aligned and contain N * 32-bit data.
638  *
639  * @param [in] pDevice Pointer to SPORT device.
640  *
641  * @param [in] pBuffer Pointer to data transfer buffer information.
642  *
643  * @return Status
644  *
645  * - #ADI_SPORT_SUCCESS Successfully submitted the buffer for data transfer.
646  *
647  * - #ADI_SPORT_BUFFERS_NOT_SUBMITTED No free descriptor for data transfer.
648  *
649  *
650  */
651 static ADI_SPORT_RESULT sport_SubmitBufferIntMode(ADI_SPORT_DEVICE * pDevice, ADI_DT_BUFF_INFO * pBuff)
652 {
654 #ifdef ADI_DEBUG
655  if ( (pBuff != pDevice->sportChannel.pFillBuffer) /* a submitted buffer should always be the current fill buffer */
656  || (true != pBuff->bInUse) /* Processed buffers should already be marked as being used */
657  || (0u != pBuff->nIndex) /* processing should start from index 0 */
658  )
659  {
660  result = ADI_SPORT_FAILED;
661  }
662  else
663 #endif /* ADI_DEBUG */
664  {
665  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
666  volatile ADI_SPORT_TypeDef * pSportRegs = pDevice->pSportInfo->pSportRegs;
667  uint32_t ctl = pSportCfg->CTL;
668  uint32_t bytesPerData = GetBytesPerSportData(ctl);
669 
679  /* use the SPORT configuration to setup the SPORT registers */
680 
681  pBuff->nCount /= bytesPerData; /* number of data to be transmitted */
682 
683 #ifdef ADI_DEBUG
684  uint32_t pack = SPORT_GET_PACKEN(pSportCfg->CTL);
685  assert( ((9u > bytesPerData) && (1u == pack)) || ((17u > bytesPerData) && (2u == pack)) || (0u == pack));
686 #endif
687  assert(pBuff->nCount <= 0xFFFu);
688  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
689 
690  ADI_INT_STATUS_ALLOC();
691  ADI_ENTER_CRITICAL_REGION();
692  pSportRegs->CTL_A = 0u; /* make sure SPORT is disable */
693  pSportRegs->NUMTRAN_A = pBuff->nCount;
694  pDevice->pSportInfo->eState = ADI_SPORT_STATE_DATA_FLOW_ENABLED;
695 
696  /* Enable SPORT Interrupt. */
697  NVIC_ClearPendingIRQ(pDevice->pSportInfo->eIRQn);
698  NVIC_EnableIRQ(pDevice->pSportInfo->eIRQn);
699  pSportRegs->IEN_A |= ((uint32_t) ( BITM_SPORT_IEN_A_DATA
700  | BITM_SPORT_IEN_A_SYSDATERR
701  | BITM_SPORT_IEN_A_FSERRMSK
702  | BITM_SPORT_IEN_A_DERRMSK
703  | BITM_SPORT_IEN_A_TF
704  )
705  );
706  pSportRegs->CTL_A = pSportCfg->CTL | ((uint32_t)BITM_SPORT_CTL_A_SPEN);
707  ADI_EXIT_CRITICAL_REGION();
708  }
709  return result;
710 }
711 
749  void ** const ppBuffer,
750  uint32_t * pHwError)
751 {
753  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) hDevice; /* Pointer to SPORT device instance */
754 
755  *ppBuffer = NULL;
756 #ifdef ADI_DEBUG
757  if (ADI_SPORT_SUCCESS != (result=ValidateHandle(pDevice))) /* Validate the given handle */
758  {
759  }
760  else
761 #endif /* ADI_DEBUG */
762  if (NULL != pDevice->pfCallback)
763  {
764  result = ADI_SPORT_FAILED;
765  } else {
766  ADI_DT_CHANNEL * pSportChnl = &pDevice->sportChannel;
767 
768  SEM_PEND(pSportChnl,ADI_SPORT_FAILED); /* wait for a submitted buffer to be processed */
769 
770  ADI_INT_STATUS_ALLOC();
771  ADI_ENTER_CRITICAL_REGION();
772  *pHwError = pDevice->nHwError;
773  pDevice->nHwError = 0u;
774  *ppBuffer = pSportChnl->pActiveBuffer->pStartAddress; /* return the buffer start address in *ppBuffer */
775  pSportChnl->pActiveBuffer->pStartAddress = NULL; /* clear the free buffer address */
776  pSportChnl->pActiveBuffer = pSportChnl->pActiveBuffer->pNextBuffer;
777  ADI_EXIT_CRITICAL_REGION();
778  if (0u != *pHwError)
779  {
780  result = ADI_SPORT_HW_ERROR;
781  }
782  }
783  return result;
784 }
785 
810  bool * const pbAvailable)
811 {
813  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) hDevice; /* Pointer to SPORT device instance */
814 
815  *pbAvailable = false;
816 #ifdef ADI_DEBUG
817  if (ADI_SPORT_SUCCESS != (result=ValidateHandle(pDevice))) /* Validate the given handle */
818  {
819  }
820  else
821 #endif /* ADI_DEBUG */
822  if (NULL != pDevice->pfCallback)
823  {
825  }
826  else
827  {
828  ADI_DT_BUFF_INFO * pActiveBuffer = pDevice->sportChannel.pActiveBuffer;
829 
830  if (pActiveBuffer->pStartAddress == NULL)
831  {
833  }
834  else if (false == pActiveBuffer->bInUse) /* this buffer has been processed by the SPORT */
835  {
836  *pbAvailable = true;
837  }
838  else
839  {
840  }
841  }
842  return result;
843 }
844 
868  ADI_CALLBACK const pfCallback,
869  void * const pCBparam)
870 {
872  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
873 #ifdef ADI_DEBUG
874  /* Validate the given handle */
875  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
876  {
877  }
878  /* Check if the data flow is already enabled */
879  else if (ADI_SPORT_STATE_DATA_FLOW_ENABLED == pDevice->pSportInfo->eState)
880  {
881  /* Not allowed to register a callback if the data flow is enabled. */
883  }
884  else
885 #endif /* ADI_DEBUG */
886  {
887  ADI_INT_STATUS_ALLOC();
888  ADI_ENTER_CRITICAL_REGION();
889  pDevice->pfCallback = pfCallback; /* Store the address of the callback function */
890  pDevice->pCBParam = pCBparam; /* Store the call back parameter */
891  ADI_EXIT_CRITICAL_REGION();
892  }
893  return result;
894 }
895 
931  const uint8_t nWordLength,
932  const ADI_SPORT_PACKING_MODE ePackMode,
933  const bool bLSBFirst
934  )
935 {
937  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
938 #ifdef ADI_DEBUG
939  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
940  {
941  }
942  if(pDevice->pSportInfo->eState == ADI_SPORT_STATE_DATA_FLOW_ENABLED) /* Not allowed to change when data flow is enabled */
943  {
945  }
946  else
947 #endif /* ADI_DEBUG */
948  if (nWordLength > SPORT_WORD_TRANSFER_LENGTH)
949  {
951  }
952  else
953  {
954  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* short cut to SPORT information */
955  ADI_SPORT_CONFIG * pSportCfg = &pSportInfo->sportCfg; /* short cut to SPORT configuration */
956  const uint32_t bytesPerData = ((nWordLength < 9u) ? (1u) : ((nWordLength < 17u) ? (2u) : (4u)));
957 
958  const uint32_t wordPos = (uint32_t) BITP_SPORT_CTL_A_SLEN;
959  const uint32_t wordLen = (uint32_t) nWordLength;
960  const uint32_t ctlSlen = (wordLen - 1u) << wordPos;
961  const uint32_t packMode = (uint32_t) ePackMode;
962  const uint32_t ctlSlenBits = (0x1Fu << wordPos);
963  const uint32_t ctlDataMask = ~(BITM_SPORT_DATA_CONFIG | ctlSlenBits | BITM_SPORT_CTL_A_LSBF);
964 
965  uint32_t ctl = pDevice->pSportInfo->sportCfg.CTL;
966  ctl &= ctlDataMask; /* clear all the fields(i.e Set to "0" ) */
967  ctl |= (packMode | ctlSlen); /* assign packing and slen information */
968  if (true == bLSBFirst)
969  {
970  ctl |= BITM_SPORT_CTL_A_LSBF; /* set the the LSB first field */
971  }
972  pDevice->pSportInfo->sportCfg.CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
973 
974  SPORT_CHECK_CFG_CTL(pDevice->pSportInfo->sportCfg.CTL);
975 
976  switch (bytesPerData)
977  {
978  case 1u:
979  if (((uint32_t) ADI_SPORT_8BIT_PACKING) == packMode)
980  {
981  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
982  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
983  } else {
984  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_1_BYTE;
985  pSportCfg->DMA_INC = ADI_DMA_INCR_1_BYTE;
986 
987  assert(((uint32_t) ADI_SPORT_NO_PACKING) == packMode);
988  }
989  break;
990 
991  case 2u:
992  if (((uint32_t) ADI_SPORT_16BIT_PACKING) == packMode)
993  {
994  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
995  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
996  } else {
997  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_2_BYTE;
998  pSportCfg->DMA_INC = ADI_DMA_INCR_2_BYTE;
999 
1000  assert(((uint32_t) ADI_SPORT_NO_PACKING) == packMode);
1001  }
1002  break;
1003 
1004  default:
1005  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1006  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1007  assert((4u == bytesPerData) || (((uint32_t) ADI_SPORT_NO_PACKING) == packMode));
1008  break;
1009  }
1010  }
1011  return result;
1012 }
1013 
1063  const uint16_t nClockRatio,
1064  const bool bUseIntlClock,
1065  const bool bRisingEdge,
1066  const bool bGatedClk)
1067 {
1069  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
1070 
1071 #ifdef ADI_DEBUG
1072  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
1073  {
1074  }
1075  else if (ADI_SPORT_STATE_DATA_FLOW_ENABLED == pDevice->pSportInfo->eState)
1076  {
1078  }
1079  else
1080 #endif /* ADI_DEBUG */
1081  {
1082  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1083  uint32_t clockRatio = (uint32_t) nClockRatio;
1084 
1085  uint32_t ctl = pSportCfg->CTL;
1086  uint32_t dv = pSportCfg->DIV;
1087 
1088  ctl &= ~BITM_SPORT_CLOCK_CONFIG; /* clear all clock configuration fields */
1089 
1090  dv &= ~BITM_SPORT_DIV_A_CLKDIV;
1091  dv |= (clockRatio & BITM_SPORT_DIV_A_CLKDIV); /* update the clock divisior value */
1092 
1093  if (true == bUseIntlClock)
1094  {
1095  ctl |= BITM_SPORT_CTL_A_ICLK; /* select the internal clock */
1096  }
1097  if (true == bRisingEdge)
1098  {
1099  ctl |= BITM_SPORT_CTL_A_CKRE; /* select the rising edge of the clock */
1100  }
1101  if (true == bGatedClk)
1102  {
1103  ctl |= BITM_SPORT_CTL_A_GCLKEN; /* Enable the Gated clock */
1104  }
1105  pDevice->pSportInfo->pSportRegs->DIV_A = pSportCfg->DIV = dv; /* DIV value set */
1106  pSportCfg->CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
1107 
1108  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1109  }
1110  return result;
1111 }
1112 
1194  const uint16_t nFsDivisor,
1195  const bool bFSRequired,
1196  const bool bInternalFS,
1197  const bool bDataFS,
1198  const bool bActiveLowFS,
1199  const bool bLateFS,
1200  const bool bFSErrorOperation)
1201 {
1202  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *) hDevice; /* Pointer to SPORT device instance */
1204 
1205 #ifdef ADI_DEBUG
1206  /* Validate the given handle */
1207  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
1208  {
1209  }
1210  else if(pDevice->pSportInfo->eState == ADI_SPORT_STATE_DATA_FLOW_ENABLED)
1211  {
1213  }
1214  else
1215 #endif /* ADI_DEBUG */
1216  {
1217  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1218  const uint32_t fsDivisor = (uint32_t) nFsDivisor;
1219 
1220  uint32_t ctl = pSportCfg->CTL;
1221  uint32_t dv = pSportCfg->DIV;
1222 
1223  dv &= ~BITM_SPORT_DIV_A_FSDIV; /* clear all the fields of frame sync */
1224  dv |= (fsDivisor << BITP_SPORT_DIV_A_FSDIV);
1225 
1226  ctl &= ~BITM_SPORT_FS_CONFIG; /* clear all the fields of frame sync */
1227 
1228  if ((ADI_SPORT_DIR_RX == pDevice->eDirection) || (true == bDataFS))
1229  {
1230  ctl |= BITM_SPORT_CTL_A_DIFS; /* Set this bit when SPORT is opened in RX mode */
1231  }
1232  if (true == bFSRequired) /* "Frame sync required" is reserved when device */
1233  { /* is operating in I2S and MC mode */
1234  ctl |= BITM_SPORT_CTL_A_FSR; /* Frame Sync(FS) is required */
1235  }
1236  if (true == bInternalFS)
1237  {
1238  ctl |= BITM_SPORT_CTL_A_IFS; /* Select the internal Frame Sync(FS)*/
1239  }
1240  if (true == bActiveLowFS)
1241  {
1242  ctl |= BITM_SPORT_CTL_A_LFS; /* Select the Active High Frame Sync(FS)*/
1243  }
1244  if (true == bLateFS)
1245  {
1246  ctl |= BITM_SPORT_CTL_A_LAFS; /* Select the Late Frame Sync(FS)*/
1247  }
1248  if (true == bFSErrorOperation)
1249  {
1250  ctl |= BITM_SPORT_CTL_A_FSERRMODE; /* Select the edge sensitive Frame Sync(FS)*/
1251  }
1252  pDevice->pSportInfo->pSportRegs->DIV_A = pSportCfg->DIV = dv; /* DIV value set */
1253  pSportCfg->CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
1254 
1255  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1256  }
1257  return result;
1258 }
1259 
1290  const bool bUseOtherFS,
1291  const bool bUseOtherClk)
1292 {
1294  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE *)hDevice; /* Pointer to SPORT device instance */
1295 #ifdef ADI_DEBUG
1296  if((result = ValidateHandle(pDevice)) != ADI_SPORT_SUCCESS) /* Validate the given handle */
1297  {
1298  }
1299  else if (pDevice->pSportInfo->eState == ADI_SPORT_STATE_DATA_FLOW_ENABLED)
1300  {
1302  }
1303  else
1304 #endif /* ADI_DEBUG */
1305  {
1306  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1307  uint32_t ctl = pSportCfg->CTL;
1308 
1309  /* clear the muxing fields of the control register 2 */
1310  ctl &= (uint32_t)(~(BITM_SPORT_CTL_A_CKMUXSEL | BITM_SPORT_CTL_A_FSMUXSEL));
1311  if (true == bUseOtherFS)
1312  {
1313  ctl |= BITM_SPORT_CTL_A_FSMUXSEL; /* Use the the frame sync of other half sport*/
1314  }
1315  if(bUseOtherClk == true)
1316  {
1317  ctl |= BITM_SPORT_CTL_A_CKMUXSEL; /* Use the the clock of other half sport*/
1318  }
1319  pSportCfg->CTL = ctl; /* CTL value set - CTL_A is assigned when submitting a buffer */
1320 
1321  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1322  }
1323 
1324  return result;
1325 }
1354  const uint8_t nFSDuration,
1355  const uint8_t nWidth,
1356  const bool bActiveLow)
1357 {
1359  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) hDevice; /* Pointer to SPORT device instance */
1360 
1361 #ifdef ADI_DEBUG /* Validate the given handle */
1362  if (ADI_SPORT_SUCCESS != (result = ValidateHandle(pDevice)))
1363  {
1364  }
1365  else if (ADI_SPORT_STATE_DATA_FLOW_ENABLED == pDevice->pSportInfo->eState)
1366  {
1368  }
1369  else
1370 #endif /* ADI_DEBUG */
1371  {
1372  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1373  uint32_t cnvt = pSportCfg->TIM_CONVT;
1374 
1375  /* clear the muxing fields of the control register 2 */
1376  cnvt &= (uint32_t)(~(BITM_SPORT_CNVT_A_POL | BITM_SPORT_CNVT_A_WID | BITM_SPORT_CNVT_A_CNVT2FS ));
1377  cnvt |= (((uint32_t) nFSDuration << ((uint32_t) BITP_SPORT_CNVT_A_CNVT2FS)) | ((uint32_t) nWidth));
1378  if(bActiveLow == true)
1379  {
1380  cnvt |= ((uint32_t) BITM_SPORT_CNVT_A_POL); /* Use the the clock of other half sport*/
1381  }
1382  pDevice->pSportInfo->pSportRegs->CNVT_A = pSportCfg->TIM_CONVT = cnvt;
1383  }
1384  return result;
1385 }
1386 
1401 static inline void sport_Init (ADI_SPORT_DEVICE *pDevice)
1402 {
1403  uint32_t i;
1404  ADI_DT_CHANNEL *pChannel = &pDevice->sportChannel;
1405  ADI_DT_BUFF_INFO *pBufInfo = &pChannel->BufInfo[0]; /* initialize this variable with the first array element */
1406  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* short cut to SPORT information */
1407  ADI_SPORT_CONFIG * pSportCfg = &pSportInfo->sportCfg; /* short cut to SPORT configuration */
1408  const uint32_t bytesPerData = GetBytesPerSportData(pSportCfg->CTL); /* number of bytes in SPORT data (1, 2, or 4) */
1409  const uint32_t packMode = SPORT_GET_PACKEN(pSportCfg->CTL); /* SPORT data pack mode */
1410 
1411  /* Initialize the all descriptors. Make it circular. */
1412  for(i = 0u; i < ADI_DT_BUFNUM; i++)
1413  {
1414  pBufInfo[i].pStartAddress = NULL;
1415  pBufInfo[i].nCount = 0u;
1416  pBufInfo[i].nIndex = 0u;
1417  pBufInfo[i].pNextBuffer = &pBufInfo[(i+1u) % ADI_DT_BUFNUM]; /* link the buffers in a circular way */
1418  }
1419  pChannel->pFreeBuffer = &pChannel->BufInfo[0u]; /* the first free buffer is the first array element */
1420  pChannel->pActiveBuffer = &pChannel->BufInfo[0u]; /* the first active buffer is the first array element */
1421  pChannel->pFillBuffer = &pChannel->BufInfo[0u]; /* the first fill buffer is the first array element */
1422 
1423  switch (bytesPerData)
1424  {
1425  case 1u:
1426  if (SPORT_BIT_PACK_8 == packMode)
1427  {
1428  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1429  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1430  } else {
1431  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_1_BYTE;
1432  pSportCfg->DMA_INC = ADI_DMA_INCR_1_BYTE;
1433 
1434  assert(SPORT_BIT_PACK_NONE == packMode);
1435  }
1436  break;
1437 
1438  case 2u:
1439  if (SPORT_BIT_PACK_16 == packMode)
1440  {
1441  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1442  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1443  } else {
1444  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_2_BYTE;
1445  pSportCfg->DMA_INC = ADI_DMA_INCR_2_BYTE;
1446 
1447  assert(SPORT_BIT_PACK_NONE == packMode);
1448  }
1449  break;
1450 
1451  default:
1452  pSportCfg->DMA_WIDTH = ADI_DMA_WIDTH_4_BYTE;
1453  pSportCfg->DMA_INC = ADI_DMA_INCR_4_BYTE;
1454  assert((4u == bytesPerData) || (SPORT_BIT_PACK_NONE == packMode));
1455  break;
1456  }
1457 }
1458 
1459 /*
1460  * @brief Configure the registers with the half-SPORT
1461  *
1462  * @param [in] hDevice Device handle to SPORT device.
1463  * @param [in] sportCfg SPORT configuration to be used.
1464  *
1465  * @return None
1466  */
1467 static inline void sport_Configure (ADI_SPORT_DEVICE *pDevice, ADI_SPORT_CONFIG const * sportCfg)
1468 {
1469  /* Configure the SPORT device using static configuration parameters.
1470  * pSportInfo is mapped to one of the half-SPORT available; this is the
1471  * half-SPORT configured. (CTL_A, DIV_A, CNVT_A and NUMTRAN_A map either
1472  * to half-SPORT A registers or half-SPORT B registers, depending on
1473  * sportRegs.)
1474  */
1475  volatile ADI_SPORT_TypeDef * sportRegs = pDevice->pSportInfo->pSportRegs;
1476  ADI_SPORT_CONFIG * pSportCfg = &pDevice->pSportInfo->sportCfg;
1477 
1478  /* record the SPORT default configuration */
1479  memcpy(pSportCfg, sportCfg, sizeof(ADI_SPORT_CONFIG));
1480 
1481  switch (pDevice->eDirection) /* Set the direction of operation */
1482  {
1483  case ADI_SPORT_DIR_RX:
1484  pSportCfg->CTL &= ~BITM_SPORT_CTL_A_SPTRAN;
1485  break;
1486  case ADI_SPORT_DIR_TX:
1487  pSportCfg->CTL |= BITM_SPORT_CTL_A_SPTRAN;
1488  break;
1489  default:
1490  assert(0);
1491  break;
1492  }
1493  /* use the SPORT configuration to setup the SPORT registers */
1494  sportRegs->CTL_A = pSportCfg->CTL;
1495  sportRegs->DIV_A = pSportCfg->DIV;
1496  sportRegs->CNVT_A = pSportCfg->TIM_CONVT;
1497  sportRegs->NUMTRAN_A = 0u;
1498 
1499  SPORT_CHECK_CFG_CTL(pSportCfg->CTL);
1500 }
1501 
1502 #ifdef ADI_DEBUG
1503 static ADI_SPORT_RESULT ValidateHandle(ADI_SPORT_HANDLE const hDevice)
1504 {
1506  ADI_SPORT_DEVICE * pInDevice = (ADI_SPORT_DEVICE*) hDevice;
1507  ADI_SPORT_DEVICE_INFO *poDeviceInfo = &gSportDevInfo[0][0];
1508  uint32_t i;
1509 
1510  /* Pointer to SPORT device instance */
1511  for (i=0u; i<(ADI_SPORT_NUM_INSTANCES << 1u); i++) /* 2 half-devices per SPORT */
1512  {
1513  if (pInDevice == poDeviceInfo->hDevice)
1514  {
1515  result = ADI_SPORT_SUCCESS;
1516  break;
1517  }
1518  poDeviceInfo++;
1519  }
1520  return result;
1521 }
1522 #endif /* ADI_DEBUG */
1523 
1524 /* mask for events to be recorded in the driver HW error */
1525 #define recEvt ((uint32_t) (BITM_SPORT_STAT_A_SYSDATERR | BITM_SPORT_STAT_A_FSERR | BITM_SPORT_STAT_A_DERR))
1526 
1527 /* bits to be cleared by the ISR */
1528 #define clrEvt ((recEvt | BITM_SPORT_STAT_A_TFI))
1529 
1530 static void sport_Terminate(ADI_SPORT_DEVICE * pDevice)
1531 {
1532  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* get SPORT device information */
1533  volatile ADI_SPORT_TypeDef * pRegs = pSportInfo->pSportRegs; /* access SPORT registers */
1534 
1535  ADI_DT_CHANNEL * pSportChnl = &pDevice->sportChannel;
1536  ADI_DT_BUFF_INFO * pBuff = pSportChnl->pFillBuffer;
1537 
1538  pRegs->CTL_A &= ~BITM_SPORT_CTL_A_SPEN; /* disable SPORT */
1539  pRegs->IEN_A &= ~(BITM_SPORT_IEN_A_TF | BITM_SPORT_IEN_A_DATA); /* disable SPORT interrupts */
1540  pRegs->NUMTRAN_A = 0u;
1541 
1542 #ifdef ADI_DEBUG
1543  {
1544  /* ============================================= */
1545  /* Check the number of data transmitted/received */
1546  /* nIndex is incremented each time a data packed */
1547  /* or unpacked in received. The size in bytes of */
1548  /* each data depends on the SPORT configuration. */
1549  /* In core driven operations, nCount represents */
1550  /* the number of 32-bit words transmitted. */
1551  /* In DMA driven operations, nCount represents */
1552  /* the number of DMA data transmitted */
1553  /* ============================================= */
1554  const uint32_t ctl = pRegs->CTL_A;
1555  const uint32_t bytesPerData = GetBytesPerSportData(ctl);
1556  const uint32_t nIndex = pBuff->nIndex * (4u / bytesPerData);
1557  assert((nIndex>=pBuff->nCount)||(true==pBuff->bDMA)); /* buffer must be fully processed */
1558  }
1559 #endif
1560 
1561  pBuff->bInUse = false; /* mark buffer as ready */
1562 
1563  NVIC_DisableIRQ(pSportInfo->eIRQn); /* suspend SPORT Interrupt */
1564  NVIC_DisableIRQ(pSportInfo->eDMAn); /* suspend SPORT DMA interrupt */
1565 
1566  pDevice->pSportInfo->eState = ADI_SPORT_STATE_PAUSED;
1567 
1568  if(NULL != pDevice->pfCallback) /* Call the callback function if one is registered. */
1569  {
1570  uint32_t evt = ( (ADI_SPORT_DIR_RX == pDevice->eDirection)
1573  );
1574 
1575  pDevice->pfCallback(pDevice->pCBParam,evt,pBuff->pStartAddress);
1576  pBuff->pStartAddress = NULL; /* No need to keep the processed buffer address */
1577  }
1578  else
1579  {
1580  SEM_POST(pSportChnl); /* signal the buffer availability through a semaphore */
1581  }
1582  pRegs->STAT_A = clrEvt; /* clear status register bits (W1C) */
1583  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONE; /* SPORT is available */
1584  pBuff = pBuff->pNextBuffer; /* point to the next buffer to process */
1585  pSportChnl->pFillBuffer = pBuff; /* this is the new pFillBuffer */
1586 
1587  if ((0u != pBuff->pStartAddress) && (true == pBuff->bInUse)) /* valid buffer not being processed yet */
1588  {
1589  ADI_SPORT_RESULT result;
1590 
1591  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONBLOCKING;
1592  if (true == pBuff->bDMA)
1593  {
1594  result = sport_SubmitBufferDmaMode(pDevice, pBuff);
1595  }
1596  else
1597  {
1598  result = sport_SubmitBufferIntMode(pDevice, pBuff);
1599  }
1600 
1601  if(ADI_SPORT_SUCCESS != result) /* if an error occurred...*/
1602  {
1603  pSportChnl->eDataTranferMode = ADI_DT_MODE_NONE; /* SPORT is available */
1604  }
1605  }
1606 }
1607 
1608 /*
1609  * @brief Common SPORT interrupt handler function called by SPORT0 A and SPORT0 B ISRs.
1610  *
1611  * @details Process SPORT0 A and B interrupts, recording HW errors that must be reported,
1612  * reading/writing transmitted data, launching new SPORT transmissions if more
1613  * buffers are to be processed, and deactivating the SPORT device if there are
1614  * no pending requests. (Common fucntion for both core driven and DMA driven
1615  * SPORT operations.)
1616  *
1617  * @param [in] pDevice Sport device pointer related to the calling ISR.
1618  */
1619 static void sport_InterruptHandler(ADI_SPORT_DEVICE * pDevice)
1620 {
1621  ADI_SPORT_DEVICE_INFO * pSportInfo = pDevice->pSportInfo; /* get SPORT device information */
1622  volatile ADI_SPORT_TypeDef * pRegs = pSportInfo->pSportRegs; /* access SPORT registers */
1623  const uint32_t sportStatus = pRegs->STAT_A; /* read SPORT status */
1624  const uint32_t dataRequest = (sportStatus & BITM_SPORT_STAT_A_DATA);/* set if any data to be processed by the SPORT */
1625  const uint32_t hwEvents = sportStatus & recEvt; /* HW events to be recorded in the driver */
1626 
1627 
1628  /* This implementation assumes an identity mapping between BITM_SPORT_STAT values
1629  * and their equivalent event in ADI_SPORT_EVENT, e.g. ADI_SPORT_HW_ERR_FS and
1630  * BITM_SPORT_STAT_A_FSERR share the same value. This simplifies event processing
1631  * and reports. */
1632  assert(((uint32_t) ADI_SPORT_HW_ERR_RX_OVERFLOW) == BITM_SPORT_STAT_A_DERR);
1633  assert(((uint32_t) ADI_SPORT_HW_ERR_TX_UNDERFLOW) == BITM_SPORT_STAT_A_DERR);
1634  assert(((uint32_t) ADI_SPORT_HW_ERR_FS) == BITM_SPORT_STAT_A_FSERR);
1635  assert(((uint32_t) ADI_SPORT_HW_ERR_SYSDATAERR) == BITM_SPORT_STAT_A_SYSDATERR);
1636 
1637  if (0u != hwEvents) /* any event recorded? */
1638  {
1639  if (NULL != pDevice->pfCallback) /* if a callback has been registered ? */
1640  {
1641  pDevice->pfCallback(pDevice->pCBParam,hwEvents,NULL); /* then call it */
1642  } else {
1643  pDevice->nHwError |= hwEvents; /* else set the driver HW error */
1644  SEM_POST(&pDevice->sportChannel); /* and signal this through a semaphore */
1645  }
1646  }
1647 
1648  if (0u != dataRequest) /* Tx FIFO is not full or Rx FIFO is not empty */
1649  {
1650  ADI_DT_BUFF_INFO * pBuff = pDevice->sportChannel.pFillBuffer;
1651  uint32_t * pNextWord = (uint32_t*) pBuff->pStartAddress;
1652 
1653  if ((NULL != pNextWord) && (pBuff->nIndex < pBuff->nCount)) /* This buffer has not been fully processed yet */
1654  {
1655  if (ADI_SPORT_DIR_RX == pDevice->eDirection)
1656  {
1657  pNextWord[pBuff->nIndex++] = pRegs->RX_A; /* Read the data received in RX and increment the index */
1658  while (!DXS_FIFO_IS_EMPTY(pRegs->STAT_A)) /* and if there are more data available in the FIFO */
1659  {
1660  pNextWord[pBuff->nIndex++] = pRegs->RX_A; /* Read remaining data received in RX and increment the index */
1661  }
1662  }
1663  else
1664  {
1665  pRegs->TX_A = pNextWord[pBuff->nIndex++]; /* Write the data to be sent into TX and increment the index */
1666  while ( (pBuff->nIndex < pBuff->nCount) /* and if there are more data to be sent */
1667  && (!DXS_FIFO_IS_FULL(pRegs->STAT_A)) /* and there is still room in the FIFO */
1668  )
1669  {
1670  pRegs->TX_A = pNextWord[pBuff->nIndex++]; /* then write more data to be sent into TX and increment the index */
1671  }
1672  }
1673  }
1674  }
1675 
1676  /* ========================================================== */
1677  /* Common to core driven operations and DMA driven operations */
1678  /* ========================================================== */
1679  if (0u != (pRegs->STAT_A & BITM_SPORT_STAT_A_TFI)) /* If a SPORT Tx/Rx request has finished */
1680  {
1681  sport_Terminate(pDevice);
1682  }
1683 
1684 #if defined(ADI_CYCLECOUNT_SPORT_ISR_ENABLED) && (ADI_CYCLECOUNT_SPORT_ISR_ENABLED == 1u)
1686 #endif
1687 }
1688 
1690 void SPORT0A_Int_Handler(void)
1691 {
1692  ISR_PROLOG();
1693  sport_InterruptHandler(gSportDevInfo[0][ADI_HALF_SPORT_A].hDevice);
1694  ISR_EPILOG();
1695 }
1696 
1698 void SPORT0B_Int_Handler(void)
1699 {
1700  ISR_PROLOG();
1701  sport_InterruptHandler(gSportDevInfo[0][ADI_HALF_SPORT_B].hDevice);
1702  ISR_EPILOG();
1703 }
1704 
1705 void DMA_SPORT0A_Int_Handler(void)
1706 {
1707  ISR_PROLOG();
1713  sport_Terminate(gSportDevInfo[0][ADI_HALF_SPORT_A].hDevice);
1714 #if defined(ADI_CYCLECOUNT_SPORT_ISR_ENABLED) && (ADI_CYCLECOUNT_SPORT_ISR_ENABLED == 1u)
1716 #endif
1717  ISR_EPILOG();
1718 }
1719 
1720 void DMA_SPORT0B_Int_Handler(void)
1721 {
1722  ISR_PROLOG();
1728  sport_Terminate(gSportDevInfo[0][ADI_HALF_SPORT_B].hDevice);
1729 #if defined(ADI_CYCLECOUNT_SPORT_ISR_ENABLED) && (ADI_CYCLECOUNT_SPORT_ISR_ENABLED == 1u)
1731 #endif
1732  ISR_EPILOG();
1733 }
1734 
1735 static void sport_DmaErrorCallback(void *pCBParam, uint32_t Event, void *pArg)
1736 {
1737  ADI_SPORT_DEVICE * pDevice = (ADI_SPORT_DEVICE*) pCBParam; /* Recover the device handle. */
1738  ADI_DT_BUFF_INFO * pFillBuffer = pDevice->sportChannel.pFillBuffer;
1739  ADI_DT_BUFF_INFO * pNextBuffer = pFillBuffer->pNextBuffer;
1740  uint32_t nEvent = 0u;
1741 
1742  if (ADI_DMA_EVENT_ERR_BUS == Event)
1743  {
1744  nEvent = (uint32_t) ADI_SPORT_DMA_ERR_BUS; /* SPORT DMA bus error detected */
1745  } else {
1746  assert(ADI_DMA_EVENT_ERR_INVALID_DESCRIPTOR == Event);
1747  nEvent = (uint32_t) ADI_SPORT_DMA_ERR_INVALID_DESCRIPTOR; /* SPORT DMA invalid descriptor error detected */
1748  }
1749 
1750  pDevice->nHwError |= nEvent;
1751  sport_InterruptHandler(pDevice);
1752 
1753  while ( (NULL != pNextBuffer->pStartAddress)
1754  && (true == pNextBuffer->bInUse)
1755  && (true == pNextBuffer->bDMA)
1756  ) /* another buffer is pending for a DMA driven request */
1757  {
1758  pDevice->nHwError |= nEvent;
1759  pNextBuffer->bInUse = false;
1760  sport_InterruptHandler(pDevice);
1761  pNextBuffer = pNextBuffer->pNextBuffer;
1762  }
1763 }
1764 
1765 static inline uint32_t GetBytesPerSportData(const uint32_t ctlVal)
1766 {
1767  const uint32_t wlen = SPORT_GET_WLEN(ctlVal);
1768  const uint32_t bytesPerData = ((wlen < 9u) ? (1u) : ((wlen < 17u) ? (2u) : (4u)));
1769  return bytesPerData;
1770 }
1771 
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:223
#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:87
#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:1289
#define ADI_CFG_SPORT0B_INTERNAL_CLK
void * ADI_SPORT_HANDLE
Definition: adi_sport.h:73
#define ADI_CFG_SPORT0B_FS_DIVISOR
ADI_SPORT_CHANNEL
Definition: adi_sport.h:78
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:930
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:379
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:1353
#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:324
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:1062
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:809
#define ADI_CYCLECOUNT_ISR_SPORT
ADI_SPORT_PACKING_MODE
Definition: adi_sport.h:96
#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:224
#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:175
#define ADI_CFG_SPORT0B_CONVT_POLARITY
ADI_SPORT_RESULT
Definition: adi_sport.h:125
#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:867
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:748
#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:1193
#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:71
#define ADI_CFG_SPORT0A_GATED_CLOCK
#define ADI_CFG_SPORT0A_ENABLE_CKMUXSEL