ADuCM4x50 Device Drivers API Reference Manual  Release 4.0.0.0
adi_crc.c
1 
15 #include <adi_processor.h>
16 #include <rtos_map/adi_rtos_map.h>
17 
18 
86 /*============= I N C L U D E S =============*/
87 
88 #include <drivers/crc/adi_crc.h>
89 #include <adi_cyclecount.h>
90 #include "adi_crc_def.h"
91 
92 /*============= M I S R A =============*/
93 
94 #ifdef __ICCARM__
95 /*
96 * IAR MISRA C 2004 error suppressions.
97 *
98 * Pm123 (rule 8.5): there shall be no definition of objects or functions in a header file
99 * This isn't a header as such.
100 *
101 * Pm088 (rule 17.4): pointer arithmetic should not be used.
102 * Pm152 (rule 17.4): array indexing shall only be applied to objects defined as an array type
103 * Relying on pointer arithmetic for buffer handling.
104 *
105 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
106 * Casts from pointer to uint32_t needed to determine pointer alignment.
107 */
108 #pragma diag_suppress=Pm123,Pm088,Pm152,Pm140
109 #endif /* __ICCARM__ */
110 
111 /*============== D E F I N E S ===============*/
112 
113 /* CRC Peripheral specific information */
114 #define ADI_CRC_NUM_DEVICES (1u)
115 
118 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT != 0)
119 
125 #ifndef ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID
126 #define ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID 7
127 #pragma message("ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID implicitly defaulted to 7!")
128 #endif
129 
138 #if (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 0)
139 #define ADI_CFG_CRC_DMA_CHANNEL SIP0_CHANn
140 #define ADI_DMA_CRC_ISR DMA_SIP0_Int_Handler
141 #define ADI_CRC_IRQ_ID DMA0_CH16_DONE_IRQn
142 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 1)
143 #define ADI_CFG_CRC_DMA_CHANNEL SIP1_CHANn
144 #define ADI_DMA_CRC_ISR DMA_SIP1_Int_Handler
145 #define ADI_CRC_IRQ_ID DMA0_CH17_DONE_IRQn
146 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 2)
147 #define ADI_CFG_CRC_DMA_CHANNEL SIP2_CHANn
148 #define ADI_DMA_CRC_ISR DMA_SIP2_Int_Handler
149 #define ADI_CRC_IRQ_ID DMA0_CH18_DONE_IRQn
150 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 3)
151 #define ADI_CFG_CRC_DMA_CHANNEL SIP3_CHANn
152 #define ADI_DMA_CRC_ISR DMA_SIP3_Int_Handler
153 #define ADI_CRC_IRQ_ID DMA0_CH19_DONE_IRQn
154 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 4)
155 #define ADI_CFG_CRC_DMA_CHANNEL SIP4_CHANn
156 #define ADI_DMA_CRC_ISR DMA_SIP4_Int_Handler
157 #define ADI_CRC_IRQ_ID DMA0_CH20_DONE_IRQn
158 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 5)
159 #define ADI_CFG_CRC_DMA_CHANNEL SIP5_CHANn
160 #define ADI_DMA_CRC_ISR DMA_SIP5_Int_Handler
161 #define ADI_CRC_IRQ_ID DMA0_CH21_DONE_IRQn
162 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 6)
163 #define ADI_CFG_CRC_DMA_CHANNEL SIP6_CHANn
164 #define ADI_DMA_CRC_ISR DMA_SIP6_Int_Handler
165 #define ADI_CRC_IRQ_ID DMA0_CH22_DONE_IRQn
166 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 7)
167 #define ADI_CFG_CRC_DMA_CHANNEL SIP7_CHANn
168 #define ADI_DMA_CRC_ISR DMA_SIP7_Int_Handler
169 #define ADI_CRC_IRQ_ID DMA0_CH23_DONE_IRQn
170 #else
171 #error "Invalid Software DMA channel identifier ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID: it must be between 0 and 7"
172 #endif
173 
174 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
175 
179 #define ADI_CRC_VALID_DEVICE_ID(DEVNUM) ((DEVNUM)<(ADI_CRC_NUM_DEVICES))
180 
182 #define ADI_CRC_DEVICE_IS_IDLE(DEV) (((DEV)->eCrcOpStatus == ADI_CRC_OP_IDLE) ? true : false)
183 
184 /*============== D A T A ===============*/
185 
189 static ADI_CRC_INFO crc_device_info[ADI_CRC_NUM_DEVICES] =
190 {
191  { pADI_CRC0, NULL } /* CRC 0 */
192 };
193 
194 /*============== M O R E D E F I N E S ===============*/
195 
197 #define ADI_CRC_INVALID_HANDLE(h) ((NULL == (h)) || (crc_device_info[0].hDevice != (h)))
198 
200 #define ADI_CRC_DEVICE_IN_USE(DEVNUM) ((NULL) != crc_device_info[(DEVNUM)].hDevice)
201 
202 #ifdef ADI_DEBUG
203 #define HDL_TO_DEVICE_PTR(HDL) ((ADI_CRC_INVALID_HANDLE(HDL)) ? (NULL) : ((ADI_CRC_DEVICE*) (HDL)))
204 #else
205 #define HDL_TO_DEVICE_PTR(HDL) ((ADI_CRC_DEVICE*) (HDL))
206 #endif
207 
208 /*============= C O D E =============*/
209 
210 #if (ADI_CRC_NUM_DEVICES!=1u)
211 #error "!!! Current CRC driver implementation can deal with a unique CRC instance !!!"
212 #endif
213 
214 /*============= L O C A L F U N C T I O N S =============*/
215 
216 /* Prototypes for static functions (required by MISRA-C:2004 Rule 8.1) */
217 
218 static ADI_CRC_INFO *crc_DeviceInfo(ADI_CRC_HANDLE hDevice);
219 
220 static void crc_ResetRegisters (ADI_CRC_DEVICE *pDevice);
221 
222 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT == 0)
223 
224 /* Functions specific to core driven CRC operations */
225 
226 static ADI_CRC_RESULT crc_ExecuteCoreDrivenOperation (ADI_CRC_DEVICE *pDevice, void *pCrcBuf, uint32_t NumBytes, uint32_t NumBits);
227 
228 #else
229 
230 /* Functions specific to DMA driven CRC operations */
231 
232 static ADI_CRC_RESULT crc_ExecuteDmaDrivenOperation(ADI_CRC_DEVICE *pDevice, void *pCrcBuf, uint32_t NumBytes, uint32_t NumBits);
233 static void crc_CalculateCrcForRemaining(ADI_CRC_DEVICE *pDevice, uint8_t *pData, uint32_t NumBytes, uint32_t NumBits);
234 static void CRC_Callback_For_DMA_Err_Int_Handler(void *pcbparam, uint32_t nEvent, void *pArg);
235 void ADI_DMA_CRC_ISR(void);
236 
237 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
238 
239 
249 static ADI_CRC_INFO *crc_DeviceInfo(ADI_CRC_HANDLE hDevice)
250 {
251  ADI_CRC_INFO *pCrcInfo = (ADI_CRC_INVALID_HANDLE(hDevice))
252  ? NULL
253  : (&(crc_device_info[0]));
254  return pCrcInfo;
255 }
256 
257 
267 static void crc_ResetRegisters(ADI_CRC_DEVICE *pDevice)
268 {
269  /* Cast the values to be assigned to the targetted types */
270  const uint32_t byte_mirroring_val = (uint32_t) ADI_CFG_CRC_ENABLE_BYTE_MIRRORING;
271  const uint32_t byte_mirroring_pos = (uint32_t) BITP_CRC_CTL_BYTMIRR;
272  const uint32_t bit_mirroring_val = (uint32_t) ADI_CFG_CRC_ENABLE_BIT_MIRRORING;
273  const uint32_t bit_mirroring_pos = (uint32_t) BITP_CRC_CTL_BITMIRR;
274  const uint32_t seed_value = (uint32_t) ADI_CFG_CRC_SEED_VALUE;
275  const uint32_t polynomial = (uint32_t) ADI_CFG_CRC_POLYNOMIAL;
276 
277  /* Set byte mirroring and bit mirroring in CTL register as configured */
278  pDevice->pReg->CTL = ( (byte_mirroring_val << byte_mirroring_pos)
279  | (bit_mirroring_val << bit_mirroring_pos)
280  );
281  pDevice->pReg->RESULT = seed_value;
282  pDevice->pReg->POLY = polynomial;
283 }
284 
285 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT == 0)
286 
287 /*
288  * @brief Starts core driven CRC operation.
289  *
290  * @param [in] pDevice Pointer to CRC device
291  * @param [in] pCrcBuf Address of data buffer.
292  * @param [in] NumBytes Number of bytes in data buffer.
293  * @param [in] NumBits Number of bits, 0 to 7, in the last partial byte
294  * in CRC data buffer
295  *
296  * @return Status
297  * - ADI_CRC_SUCCESS: Successfully set expected CRC result.
298  */
299 static ADI_CRC_RESULT crc_ExecuteCoreDrivenOperation(
300  ADI_CRC_DEVICE *pDevice,
301  void *pCrcBuf,
302  uint32_t NumBytes,
303  uint32_t NumBits)
304 {
306  uint8_t *pData = (uint8_t *)pCrcBuf; /* initialize the pointer to data to the start of the data buffer */
307  uint32_t lsbFirst = pDevice->pReg->CTL & BITM_CRC_CTL_LSBFIRST;
308 
309  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN);
311  if (((uint32_t)pData & 0x3u) != 0u) /* If the buffer is not 4-byte aligned */
312  {
313  /* feed the CRC byte per byte as long as there are data in the input buffer AND
314  * the data left in the buffer are not 4-byte aligned */
315  while ((NumBytes > 0u) && (((uint32_t)pData & 0x3u) != 0u))
316  {
317  pDevice->pReg->IPBYTE = *pData; /* feed the CRC with the first byte in the buffer */
318  pData++; /* get the next byte to feed into CRC */
319  NumBytes--; /* decrease the number of bytes to be processed */
320  }
321  }
322 
323  /* data left in the input buffer are now 4-byte aligned */
324 
325  while (NumBytes >= 4u) /* if the number of bytes left is greater than 4 bytes */
326  { /* feed CRC peripheral with 4-byte data */
327  uint32_t nData; /* 32-bit variable to be used to feed the CRC peripheral */
328 
329  /*
330  * Here we assume memory is little endian. We need change the following
331  * code if we produce a Cortex-M processor with big endian memory.
332  */
333  if (lsbFirst != 0u)
334  {
335  nData = pData[3];
336  nData = (nData << 8) | pData[2];
337  nData = (nData << 8) | pData[1];
338  nData = (nData << 8) | pData[0];
339  }
340  else
341  {
342  nData = pData[0];
343  nData = (nData << 8) | pData[1];
344  nData = (nData << 8) | pData[2];
345  nData = (nData << 8) | pData[3];
346  }
347  pDevice->pReg->IPDATA = nData; /* feed the CRC peripheral with 32-bit data input */
348  pData += 4; /* move the data pointer in the data buffer */
349  NumBytes -= 4u; /* decrease the number of data to be processed */
350  }
351 
352  while (NumBytes > 0u) /* if the number of data left in the input buffer is smaller than 4 */
353  {
354  pDevice->pReg->IPBYTE = *pData; /* feed the CRC peripheral with the remaining bytes */
355  pData++; /* move the pointer to the next byte in input data buffer */
356  NumBytes--; /* decrease the number of data to be fed into the CRC peripheral */
357  }
358 
359  if (NumBits > 0u) /* if the last byte is a partial byte containing less than 8 bits */
360  {
361  pDevice->pReg->IPBITS[NumBits] = *pData;/* feed the CRC peripheral with the remaining bits (use IPBITS[N] to feed N bits) */
362  }
363 
364  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_EN); /* All the data have been fed into the CRC peripheral : disable it */
365  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* CRC back in idle state */
366  return result;
367 }
368 
369 #else /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
370 
385 static ADI_CRC_RESULT crc_ExecuteDmaDrivenOperation(
386  ADI_CRC_DEVICE *pDevice,
387  void *pCrcBuf,
388  uint32_t NumBytes,
389  uint32_t NumBits)
390 {
392  uint8_t *pData = (uint8_t *)pCrcBuf;
393  bool bUseDma = false; /* assume core driven CRC by default */
394 
395 #ifdef ADI_DEBUG
396  if (!ADI_CRC_VALID_DMA_CHANNEL(ADI_CFG_CRC_DMA_CHANNEL))
397  {
398  /* Report error as Memory DMA not open */
400  }
401  else
402 #endif /* ADI_DEBUG */
403  {
404  /* If LSBFIRST, it's easy. */
405  if ((pDevice->pReg->CTL & BITM_CRC_CTL_LSBFIRST) != 0u)
406  {
407  /* If the buffer is not 4-byte aligned */
408  if (((uint32_t)pData & 0x3u) != 0u)
409  {
410  /* process the first bytes until a 4-byte aligned data location is reached */
411  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN); /* enable CRC */
412  while ((NumBytes > 0u) && (((uint32_t)pData & 0x3u) != 0u))
413  {
414  pDevice->pReg->IPBYTE = *pData; /* feed byte into CRC */
415  pData++; /* get to the next byte */
416  NumBytes--; /* decrease the number of bytes still to be processed */
417  }
418  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_EN); /* disable CRC */
419  }
420 
421  /* 4-byte aligned data transfer */
422  if (NumBytes >= 4u)
423  {
424  /* there are enough data for kicking off a DMA driven CRC operation */
425  const uint32_t channelId = (uint32_t) ADI_CFG_CRC_DMA_CHANNEL;
426  const uint32_t channelBit = 1ul << channelId; /* get a value with the bit set at position identified by channelId */
427  const uint32_t numData = NumBytes / 4u; /* number of 4-byte data to be transferred */
428  const uint32_t src = (uint32_t) pData; /* DMA source address */
429  const uint32_t dst = (uint32_t) &pDevice->pReg->IPDATA; /* destination is CRC IPDATA 32-bit register */
430  const uint32_t numTransData = ( (numData > DMA_TRANSFER_LIMIT)
431  ? DMA_TRANSFER_LIMIT
432  : numData
433  );
434  const uint32_t numTransBytes = (numTransData << 2u);
435  const uint32_t lastDataPos = (numTransBytes - 4u); /* position of last 32-bit data to be transferred in current DMA request */
436 
437  pDevice->pReg->CTL |= ((uint32_t) BITM_CRC_CTL_EN); /* enable CRC (leave other bits unmodified) */
438 
439  pADI_DMA0->EN_SET = channelBit; /* Enable the channel */
440  pADI_DMA0->ALT_CLR = channelBit; /* Set the primary as the current DMA descriptor */
441  pADI_DMA0->SRCADDR_CLR = channelBit; /* Ensure decrement for source is cleared */
442  pADI_DMA0->DSTADDR_CLR = channelBit; /* Ensure decrement for destination is cleared */
443 
444  pPrimaryCCD[channelId].DMADSTEND = dst; /* destination is CRC IPDATA 32-bit register */
445  pPrimaryCCD[channelId].DMASRCEND = src + lastDataPos; /* source end address */
446 
447  pPrimaryCCD[channelId].DMACDC =
448  ( (((uint32_t) ADI_DMA_INCR_NONE) << ((uint32_t) DMA_BITP_CTL_DST_INC)) /* destination address not incremented */
449  | (((uint32_t) ADI_DMA_INCR_4_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_INC)) /* source address incremented by 4 bytes */
450  | (((uint32_t) ADI_DMA_WIDTH_4_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_SIZE)) /* source data size is 4-byte */
451  | ((numTransData - 1u) << ((uint32_t) DMA_BITP_CTL_N_MINUS_1))/* number of DMA transfers (minus 1) */
452  | (DMA_ENUM_CTL_CYCLE_CTL_AUTO_REQ << DMA_BITP_CTL_CYCLE_CTL) /* DMA Auto Request transmission */
453  );
454  pDevice->pRemainingData = (void*)(src + numTransBytes); /* remaining data start address */
455  pDevice->RemainingBytes = NumBytes - numTransBytes; /* remaining bytes that cannot be processed in this DMA batch */
456  pDevice->RemainingBits = NumBits; /* remaining bits if last byte is a partial byte */
457  bUseDma = true; /* there are enough data to run 4-byte DMA transfers to CRC */
458  }
459  }
460  /*
461  * If ! LSBFIRST, we need the DMA controller support byte swap for fixed destination address.
462  * But we don't have such luck, although it supports byte swap for fixed source address.
463  * So we have to set DMA size to one byte, which is slower.
464  *
465  * Another option is using mirroring feature of CRC unit, which would be more complicated.
466  */
467  else
468  {
469  if (NumBytes > 0u)
470  {
478  const uint32_t channelId = (uint32_t) ADI_CFG_CRC_DMA_CHANNEL;
479  const uint32_t channelBit = 1ul << channelId; /* get a value with the bit set at position identified by channelId */
480  const uint32_t src = (uint32_t) pData; /* DMA source address */
481  const uint32_t dst = (uint32_t) &pDevice->pReg->IPBYTE; /* destination is CRC IPBYTE 8-bit register */
482  const uint32_t numTransData = ( (NumBytes > DMA_TRANSFER_LIMIT)
483  ? DMA_TRANSFER_LIMIT
484  : NumBytes
485  );
486  const uint32_t lastDataPos = (numTransData - 1u); /* position of last data to be transferred in buffer */
487 
488  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN); /* enable CRC (leave other bits unmodified) */
489 
490  pADI_DMA0->EN_SET = channelBit; /* Enable the channel */
491  pADI_DMA0->ALT_CLR = channelBit; /* Set the primary as the current DMA descriptor */
492  pADI_DMA0->SRCADDR_CLR = channelBit; /* Ensure decrement for source is cleared */
493  pADI_DMA0->DSTADDR_CLR = channelBit; /* Ensure decrement for destination is cleared */
494 
495  pPrimaryCCD[channelId].DMADSTEND = dst; /* destination is CRC IPBYTE 8-bit register */
496  pPrimaryCCD[channelId].DMASRCEND = src + lastDataPos; /* source end address */
497  pPrimaryCCD[channelId].DMACDC =
498  ( (((uint32_t) ADI_DMA_INCR_NONE) << ((uint32_t) DMA_BITP_CTL_DST_INC)) /* destination address not incremented */
499  | (((uint32_t) ADI_DMA_INCR_1_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_INC)) /* source address incremented by 1 byte */
500  | (((uint32_t) ADI_DMA_WIDTH_1_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_SIZE)) /* source data size is 1-byte */
501  | ((numTransData - 1u) << ((uint32_t) DMA_BITP_CTL_N_MINUS_1))/* number of DMA transfers (minus 1) */
502  | (DMA_ENUM_CTL_CYCLE_CTL_AUTO_REQ << DMA_BITP_CTL_CYCLE_CTL) /* DMA Auto Request transmission */
503  );
504  pDevice->pRemainingData = (void*) (src + numTransData); /* remaining data start address */
505  pDevice->RemainingBytes = NumBytes - numTransData; /* remaining bytes */
506  pDevice->RemainingBits = NumBits; /* remaining bits if last byte is a partial byte */
507  bUseDma = true; /* there are enough data to run 4-byte DMA transfers to CRC */
508  }
509  }
510 
511  /* if we are in a position to use the DMA to transfer data to the CRC */
512  if (bUseDma== true)
513  {
514  const uint32_t channelId = (uint32_t) ADI_CFG_CRC_DMA_CHANNEL;
515  const uint32_t channelBit = 1ul << channelId; /* get a value with the bit set at position identified by channelId */
516  pADI_DMA0->SWREQ = channelBit; /* Issue a software DMA request */
517  }
518  else
519  {
520  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN);
521  crc_CalculateCrcForRemaining(pDevice, pData, NumBytes, NumBits);
522  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_EN);
523  if(pDevice->pfCallback != NULL)
524  {
525  pDevice->pfCallback(pDevice->pCBParam, (uint32_t) ADI_CRC_EVENT_BUFFER_PROCESSED, pData);
526  }
527  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* CRC calculation completed */
528  }
529  }
530  return result;
531 }
532 
543 static void crc_CalculateCrcForRemaining(ADI_CRC_DEVICE *pDevice, uint8_t *pData, uint32_t NumBytes, uint32_t NumBits)
544 {
545  /* process the remaining bytes */
546  while (NumBytes > 0u)
547  {
548  pDevice->pReg->IPBYTE = *pData;
549  pData++;
550  NumBytes--;
551  }
552 
553  /* process the remaining bits in the last byte if the number of bits is smaller than 8 */
554  if (NumBits > 0u)
555  {
556  pDevice->pReg->IPBITS[NumBits] = *pData;
557  }
558 }
559 
566 static void CRC_Callback_For_DMA_Err_Int_Handler(void *pcbparam, uint32_t nEvent, void *pArg)
567 {
568  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(pcbparam);
569 
570  if (NULL != pDevice)
571  {
572  /* DMA error detected */
573  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* mark the CRC peripheral as IDLE */
574  pDevice->pReg->CTL &= (uint32_t)(~(BITM_CRC_CTL_EN)); /* disable CRC peripheral */
575  }
576 }
577 
586 void ADI_DMA_CRC_ISR(void)
587 {
588  ISR_PROLOG();
589 
590  if (ADI_CRC_DEVICE_IN_USE(0))
591  {
592  ADI_CRC_DEVICE * pDevice = HDL_TO_DEVICE_PTR(crc_device_info[0].hDevice);
593  if (NULL != pDevice)
594  {
595  uint8_t *pData = (uint8_t *)(pDevice->pRemainingData);
596  uint32_t NumBytes = pDevice->RemainingBytes;
597  uint32_t NumBits = pDevice->RemainingBits;
598  bool finishing = (NumBytes < 4u);
599 
600  if (!finishing)
601  {
602  /* there's enough data left for another DMA transfer */
603  ADI_CRC_RESULT result = pDevice->pfSubmitBuffer(pDevice, pData, NumBytes, NumBits);
604  if (ADI_CRC_SUCCESS != result)
605  {
606  /* buffer submission failed: complete the task through core driven operations */
607  finishing = true;
608  }
609  }
610 
611  if (finishing)
612  {
613  /* There are a very few bytes/bits left to be processed or
614  * a DMA transfer request could not be sent */
615  crc_CalculateCrcForRemaining(pDevice, pData, NumBytes, NumBits);
616 
617  /* if a callback function is registered with the interrupt handler
618  * associated with the software DMA channel driving the CRC */
619  if(pDevice->pfCallback != NULL)
620  {
621  pDevice->pfCallback(pDevice->pCBParam, (uint32_t) ADI_CRC_EVENT_BUFFER_PROCESSED, NULL);
622  }
623  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* CRC back in idle state */
624 
625  }
626  }
627  }
628 
629 #if defined(ADI_CYCLECOUNT_CRC_ISR_ENABLED) && (ADI_CYCLECOUNT_CRC_ISR_ENABLED == 1u)
631 #endif
632 
633  ISR_EPILOG();
634 }
635 
636 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
637 
640 /*============= P U B L I C F U N C T I O N S =============*/
641 
662  uint32_t DeviceNum,
663  void *pMemory,
664  uint32_t MemorySize,
665  ADI_CRC_HANDLE *phDevice)
666 {
668  ADI_CRC_DEVICE *pDevice = (ADI_CRC_DEVICE*) pMemory;/* memory block to be used to manage a CRC driver instance */
669 
670 #ifdef ADI_DEBUG /* IF (Debug information enabled) */
671  if (!ADI_CRC_VALID_DEVICE_ID(DeviceNum)) /* IF (This is not a valid CRC device number) */
672  {
673  result = ADI_CRC_BAD_DEVICE_NUMBER; /* Report failure as bad device number */
674  }
675  else if (ADI_CRC_DEVICE_IN_USE(DeviceNum)) /* IF (The device is in use) */
676  {
677  result = ADI_CRC_IN_USE; /* return CRC Device in use error */
678  }
679  else if ( (MemorySize < ADI_CRC_MEMORY_SIZE) /* IF (Supplied memory size is insufficient) */
680  || (ADI_CRC_MEMORY_SIZE < sizeof(ADI_CRC_DEVICE))
681  )
682  {
683  result = ADI_CRC_INSUFFICIENT_MEMORY; /* Report failure as insufficient memory */
684  }
685  else
686 #endif /* ADI_DEBUG */
687  {
688  /* check that ADI_CRC_MEMORY_SIZE is accurately defined */
689  assert(ADI_CRC_MEMORY_SIZE == sizeof(ADI_CRC_DEVICE));
690 
691  memset(pMemory, 0, MemorySize); /* Clear the given memory */
692 
693  ADI_INT_STATUS_ALLOC();
694  ADI_ENTER_CRITICAL_REGION(); /* Entering critical region, disable interrupts */
695 
696  /* Save the supplied device memory address */
697  crc_device_info[DeviceNum].hDevice = (ADI_CRC_HANDLE)pDevice;
698  pDevice->pReg = crc_device_info[DeviceNum].pReg;
699 
700  ADI_EXIT_CRITICAL_REGION(); /* Re-enable interrupts */
701 
702  crc_ResetRegisters(pDevice); /* Reset CRC registers */
703  *phDevice = crc_device_info[DeviceNum].hDevice; /* Pass a valid handle to this CRC device */
704 
705 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT == 0)
706 
707  pDevice->pfSubmitBuffer = &crc_ExecuteCoreDrivenOperation;
708 
709 #else /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
710 
711  pDevice->pfSubmitBuffer = &crc_ExecuteDmaDrivenOperation;
712  adi_dma_Init();
713 
714  /* Register CRC DMA callback */
715 #ifdef ADI_DEBUG /* IF (Debug information enabled) */
716  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,CRC_Callback_For_DMA_Err_Int_Handler,pDevice))
717  {
718  result = ADI_CRC_FAILURE;
719  }
720 #else
721  adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,CRC_Callback_For_DMA_Err_Int_Handler,pDevice);
722 #endif
723  NVIC_EnableIRQ(ADI_CRC_IRQ_ID); /* Enable the interrupt for the DMA channel used by CRC */
724 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
725  }
726  return result;
727 }
728 
740 {
742  ADI_CRC_INFO *pCrcInfo = crc_DeviceInfo(hDevice); /* get CRC info pointer from CRC handle */
743 #ifdef ADI_DEBUG
744  if (NULL == pCrcInfo)
745  {
746  result = ADI_CRC_BAD_HANDLE; /* invalid CRC handle being used */
747  }
748  else
749 #endif
750  {
751 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT != 0)
752  NVIC_DisableIRQ(ADI_CRC_IRQ_ID); /* Disable the interrupt for the DMA channel used by CRC. */
753  /* Register CRC DMA callback */
754 #ifdef ADI_DEBUG /* IF (Debug information enabled) */
755  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,NULL,NULL))
756  {
757  result = ADI_CRC_FAILURE;
758  }
759 #else
760  adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,NULL,NULL);
761 #endif
762 #endif
763  pCrcInfo->hDevice = NULL; /* Mark CRC driver as closed */
764  }
765  return result;
766 }
784 ADI_CRC_RESULT adi_crc_SetBitMirroring(ADI_CRC_HANDLE const hDevice, const bool bEnable)
785 {
787  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice); /* get CRC device pointer from CRC handle */
788 
789 #ifdef ADI_DEBUG
790  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
791  {
792  result = ADI_CRC_BAD_HANDLE;
793  }
794  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
795  {
796  result = ADI_CRC_FN_NOT_PERMITTED; /* Function not permitted when CRC operation is in progress */
797  }
798  else
799 #endif
800  if(bEnable == true)
801  {
802  pDevice->pReg->CTL |= (BITM_CRC_CTL_BITMIRR); /* enable bit mirroring */
803  }
804  else
805  {
806  pDevice->pReg->CTL &= (uint32_t)(~(BITM_CRC_CTL_BITMIRR)); /* disable bit mirroring */
807  }
808  return result;
809 }
827 ADI_CRC_RESULT adi_crc_SetByteMirroring(ADI_CRC_HANDLE const hDevice, const bool bEnable)
828 {
830  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice); /* get CRC device pointer from CRC handle */
831 
832 #ifdef ADI_DEBUG
833  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
834  {
835  result = ADI_CRC_BAD_HANDLE;
836  }
837  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
838  {
839  result = ADI_CRC_FN_NOT_PERMITTED; /* Function not permitted when CRC operation is in progress */
840  }
841  else
842 #endif
843  if(bEnable == true)
844  {
845  pDevice->pReg->CTL |= (BITM_CRC_CTL_BYTMIRR); /* enable byte mirroring */
846  }
847  else
848  {
849  pDevice->pReg->CTL &= (uint32_t)(~(BITM_CRC_CTL_BYTMIRR)); /* disable byte mirroring */
850  }
851  return result;
852 }
853 
872 ADI_CRC_RESULT adi_crc_SetLSBFirst(ADI_CRC_HANDLE const hDevice, const bool bEnable)
873 {
875  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice); /* get CRC device pointer from CRC handle */
876 
877 #ifdef ADI_DEBUG
878  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
879  {
880  result = ADI_CRC_BAD_HANDLE;
881  }
882  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
883  {
884  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
885  }
886  else
887 #endif
888  if(bEnable == true)
889  {
890  pDevice->pReg->CTL |= (BITM_CRC_CTL_LSBFIRST); /* enable LSB first (MSB first disable) */
891  }
892  else
893  {
894  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_LSBFIRST); /* disable LSB first (MSB first enable) */
895  }
896  return result;
897 }
915 ADI_CRC_RESULT adi_crc_EnableWordSwap(ADI_CRC_HANDLE const hDevice, const bool bEnable)
916 {
918  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
919 
920 #ifdef ADI_DEBUG
921  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
922  {
923  result = ADI_CRC_BAD_HANDLE;
924  }
925  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
926  {
927  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
928  }
929  else
930 #endif
931  if(bEnable == true)
932  {
933  pDevice->pReg->CTL |= BITM_CRC_CTL_W16SWP; /* enable word swap */
934  }
935  else
936  {
937  pDevice->pReg->CTL &= ~BITM_CRC_CTL_W16SWP; /* disable word swap */
938  }
939 
940  return result;
941 }
955  ADI_CRC_HANDLE const hDevice,
956  uint32_t CrcSeedVal)
957 {
959  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
960 
961 #ifdef ADI_DEBUG
962  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
963  {
964  result = ADI_CRC_BAD_HANDLE;
965  }
966  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
967  {
968  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
969  }
970  else
971 #endif /* ADI_DEBUG */
972  {
973  pDevice->pReg->RESULT = CrcSeedVal; /* Load the CRC seed value */
974  }
975  return result;
976 }
977 
991  ADI_CRC_HANDLE const hDevice,
992  uint32_t PolynomialVal)
993 {
995  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
996 
997 #ifdef ADI_DEBUG
998  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
999  {
1000  result = ADI_CRC_BAD_HANDLE;
1001  }
1002  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
1003  {
1004  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
1005  }
1006  else
1007 #endif /* ADI_DEBUG */
1008  {
1009  pDevice->pReg->POLY = PolynomialVal; /* Load Polynomial value */
1010  }
1011  return result;
1012 }
1013 
1038  ADI_CRC_HANDLE const hDevice,
1039  void *pCrcBuf,
1040  uint32_t NumBytes,
1041  uint32_t NumBits)
1042 {
1044  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1045 #ifdef ADI_DEBUG
1046  if (NumBits >= 8u)
1047  {
1048  result = ADI_CRC_INVALID_PARAMETER;
1049  }
1050  else if (NULL == pDevice)
1051  {
1052  result = ADI_CRC_BAD_HANDLE;
1053  }
1054  else if (((pDevice->pReg->CTL & BITM_CRC_CTL_REVID) == 0u) && (NumBits != 0u))
1055  {
1056  result = ADI_CRC_FN_NOT_SUPPORTED; /* Partial byte needs CRC unit revision 1 or up */
1057  }
1058  else
1059  if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
1060  {
1061  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
1062  }
1063  else
1064 #endif /* ADI_DEBUG */
1065  {
1066  pDevice->eCrcOpStatus = ADI_CRC_OP_IN_PROGRESS; /* mark the CRC as in progress */
1067  result = pDevice->pfSubmitBuffer(pDevice, pCrcBuf, NumBytes, NumBits);
1068 
1069  /* CRC returns in IDLE mode when it has processed all its data, not after submitting a request */
1070  }
1071  return result;
1072 }
1073 
1089  ADI_CRC_HANDLE const hDevice,
1090  bool *pbCrcInProgress)
1091 {
1093  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1094 
1095 #ifdef ADI_DEBUG
1096  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1097  {
1098  result = ADI_CRC_BAD_HANDLE;
1099  }
1100  else
1101 #endif /* ADI_DEBUG */
1102  {
1103 
1104  if ((pDevice)->eCrcOpStatus == ADI_CRC_OP_IN_PROGRESS)
1105  {
1106  *pbCrcInProgress = true;
1107 
1108  }
1109  else
1110  {
1111  *pbCrcInProgress = false;
1112 
1113  }
1114  }
1115  return result;
1116 }
1117 
1140  ADI_CRC_HANDLE const hDevice,
1141  uint32_t *pFinalCrcVal)
1142 {
1144  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1145 
1146 #ifdef ADI_DEBUG
1147  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1148  {
1149  result = ADI_CRC_BAD_HANDLE;
1150  }
1151  else
1152 #endif /* ADI_DEBUG */
1153  {
1154  const uint32_t seed_value = (uint32_t) ADI_CFG_CRC_SEED_VALUE;
1155  *pFinalCrcVal = pDevice->pReg->RESULT; /* Get the final CRC result */
1156  pDevice->pReg->RESULT = seed_value;
1157  }
1158  return result;
1159 }
1160 
1173  ADI_CRC_HANDLE const hDevice,
1174  uint32_t *pCurrentCrcVal)
1175 {
1177  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1178 
1179 #ifdef ADI_DEBUG
1180  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1181  {
1182  result = ADI_CRC_BAD_HANDLE;
1183  }
1184  else
1185 #endif /* ADI_DEBUG */
1186  {
1187  *pCurrentCrcVal = pDevice->pReg->RESULT; /* Get the current CRC result */
1188  }
1189 
1190  return result;
1191 }
1192 
1219  ADI_CRC_HANDLE const hDevice,
1220  ADI_CALLBACK pfCallback,
1221  void *const pCBParam)
1222 {
1224  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1225 
1226  ADI_INT_STATUS_ALLOC();
1227  ADI_ENTER_CRITICAL_REGION(); /* Entering critical region, disable interrupts */
1228 
1229 #ifdef ADI_DEBUG
1230  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1231  {
1232  result = ADI_CRC_BAD_HANDLE;
1233  }
1234  else
1235 #endif /* ADI_DEBUG */
1236  {
1237  /* Update CRC Callback information */
1238  pDevice->pfCallback = pfCallback;
1239  pDevice->pCBParam = pCBParam;
1240  }
1241 
1242  ADI_EXIT_CRITICAL_REGION(); /* Re-enable interrupts */
1243 
1244  return result;
1245 }
1246 
1247 
1248 /*****/
1249 
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_CRC_SEED_VALUE
struct __ADI_CRC_DEVICE * ADI_CRC_HANDLE
Definition: adi_crc.h:112
#define ADI_CYCLECOUNT_STORE(id)
ADI_CRC_RESULT adi_crc_GetCurrentCrcVal(ADI_CRC_HANDLE const hDevice, uint32_t *pCurrentCrcVal)
Gets the current/intermediate CRC result computed for a data stream.
Definition: adi_crc.c:1172
ADI_CRC_RESULT adi_crc_RegisterCallback(ADI_CRC_HANDLE const hDevice, ADI_CALLBACK pfCallback, void *const pCBParam)
Registers or unregisters a callback with the CRC device.
Definition: adi_crc.c:1218
#define ADI_CRC_MEMORY_SIZE
Definition: adi_crc.h:60
ADI_CRC_RESULT adi_crc_SetByteMirroring(ADI_CRC_HANDLE const hDevice, const bool bEnable)
Set the byte mirroring. This function should be called only when device is disabled.
Definition: adi_crc.c:827
ADI_CRC_RESULT adi_crc_SetPolynomialVal(ADI_CRC_HANDLE const hDevice, uint32_t PolynomialVal)
Sets the 32-bit polynomial for CRC operations.
Definition: adi_crc.c:990
ADI_CRC_RESULT adi_crc_SetLSBFirst(ADI_CRC_HANDLE const hDevice, const bool bEnable)
Enable the LSB first.
Definition: adi_crc.c:872
ADI_CRC_RESULT adi_crc_Open(uint32_t DeviceNum, void *pMemory, uint32_t MemorySize, ADI_CRC_HANDLE *phDevice)
Opens a CRC device instance.
Definition: adi_crc.c:661
ADI_CRC_RESULT adi_crc_IsCrcInProgress(ADI_CRC_HANDLE const hDevice, bool *pbCrcInProgress)
Gets the current CRC peripheral status.
Definition: adi_crc.c:1088
ADI_CRC_RESULT
Definition: adi_crc.h:117
ADI_CRC_RESULT adi_crc_Close(ADI_CRC_HANDLE const hDevice)
Closes CRC device instance opened for use.
Definition: adi_crc.c:739
ADI_CRC_RESULT adi_crc_GetFinalCrcVal(ADI_CRC_HANDLE const hDevice, uint32_t *pFinalCrcVal)
Gets the final CRC result computed for a data stream.
Definition: adi_crc.c:1139
ADI_CRC_RESULT adi_crc_EnableWordSwap(ADI_CRC_HANDLE const hDevice, const bool bEnable)
To enable/disable the word Swap. This function should be called only when device is disabled.
Definition: adi_crc.c:915
ADI_CRC_RESULT adi_crc_SetCrcSeedVal(ADI_CRC_HANDLE const hDevice, uint32_t CrcSeedVal)
Sets the initial seed value for the CRC operation that is about to take place.
Definition: adi_crc.c:954
ADI_CRC_RESULT adi_crc_Compute(ADI_CRC_HANDLE const hDevice, void *pCrcBuf, uint32_t NumBytes, uint32_t NumBits)
Submits data buffer for CRC computation.
Definition: adi_crc.c:1037
#define ADI_CFG_CRC_ENABLE_BIT_MIRRORING
void adi_dma_Init(void)
Initialize the DMA peripheral.
Definition: adi_dma.c:155
#define ADI_CFG_CRC_ENABLE_BYTE_MIRRORING
#define ADI_CFG_CRC_POLYNOMIAL
#define ADI_CYCLECOUNT_ISR_CRC
ADI_CRC_RESULT adi_crc_SetBitMirroring(ADI_CRC_HANDLE const hDevice, const bool bEnable)
Set the bit mirroring. This function should be called only when device is idle, i....
Definition: adi_crc.c:784