ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_crc.c
1 
46 #include <adi_processor.h>
47 #include <rtos_map/adi_rtos_map.h>
48 
49 
117 /*============= I N C L U D E S =============*/
118 
119 #include <drivers/crc/adi_crc.h>
120 #include <adi_cyclecount.h>
121 #include "adi_crc_def.h"
122 
123 /*============= M I S R A =============*/
124 
125 #ifdef __ICCARM__
126 /*
127 * IAR MISRA C 2004 error suppressions.
128 *
129 * Pm123 (rule 8.5): there shall be no definition of objects or functions in a header file
130 * This isn't a header as such.
131 *
132 * Pm088 (rule 17.4): pointer arithmetic should not be used.
133 * Pm152 (rule 17.4): array indexing shall only be applied to objects defined as an array type
134 * Relying on pointer arithmetic for buffer handling.
135 *
136 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
137 * Casts from pointer to uint32_t needed to determine pointer alignment.
138 */
139 #pragma diag_suppress=Pm123,Pm088,Pm152,Pm140
140 #endif /* __ICCARM__ */
141 
142 /*============== D E F I N E S ===============*/
143 
144 /* CRC Peripheral specific information */
145 #define ADI_CRC_NUM_DEVICES (1u)
146 
149 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT != 0)
150 
156 #ifndef ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID
157 #define ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID 7
158 #pragma message("ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID implicitly defaulted to 7!")
159 #endif
160 
169 #if (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 0)
170 #define ADI_CFG_CRC_DMA_CHANNEL SIP0_CHANn
171 #define ADI_DMA_CRC_ISR DMA_SIP0_Int_Handler
172 #define ADI_CRC_IRQ_ID DMA0_CH16_DONE_IRQn
173 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 1)
174 #define ADI_CFG_CRC_DMA_CHANNEL SIP1_CHANn
175 #define ADI_DMA_CRC_ISR DMA_SIP1_Int_Handler
176 #define ADI_CRC_IRQ_ID DMA0_CH17_DONE_IRQn
177 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 2)
178 #define ADI_CFG_CRC_DMA_CHANNEL SIP2_CHANn
179 #define ADI_DMA_CRC_ISR DMA_SIP2_Int_Handler
180 #define ADI_CRC_IRQ_ID DMA0_CH18_DONE_IRQn
181 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 3)
182 #define ADI_CFG_CRC_DMA_CHANNEL SIP3_CHANn
183 #define ADI_DMA_CRC_ISR DMA_SIP3_Int_Handler
184 #define ADI_CRC_IRQ_ID DMA0_CH19_DONE_IRQn
185 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 4)
186 #define ADI_CFG_CRC_DMA_CHANNEL SIP4_CHANn
187 #define ADI_DMA_CRC_ISR DMA_SIP4_Int_Handler
188 #define ADI_CRC_IRQ_ID DMA0_CH20_DONE_IRQn
189 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 5)
190 #define ADI_CFG_CRC_DMA_CHANNEL SIP5_CHANn
191 #define ADI_DMA_CRC_ISR DMA_SIP5_Int_Handler
192 #define ADI_CRC_IRQ_ID DMA0_CH21_DONE_IRQn
193 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 6)
194 #define ADI_CFG_CRC_DMA_CHANNEL SIP6_CHANn
195 #define ADI_DMA_CRC_ISR DMA_SIP6_Int_Handler
196 #define ADI_CRC_IRQ_ID DMA0_CH22_DONE_IRQn
197 #elif (ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID == 7)
198 #define ADI_CFG_CRC_DMA_CHANNEL SIP7_CHANn
199 #define ADI_DMA_CRC_ISR DMA_SIP7_Int_Handler
200 #define ADI_CRC_IRQ_ID DMA0_CH23_DONE_IRQn
201 #else
202 #error "Invalid Software DMA channel identifier ADI_CFG_CRC_SOFTWARE_DMA_CHANNEL_ID: it must be between 0 and 7"
203 #endif
204 
205 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
206 
210 #define ADI_CRC_VALID_DEVICE_ID(DEVNUM) ((DEVNUM)<(ADI_CRC_NUM_DEVICES))
211 
213 #define ADI_CRC_DEVICE_IS_IDLE(DEV) (((DEV)->eCrcOpStatus == ADI_CRC_OP_IDLE) ? true : false)
214 
215 /*============== D A T A ===============*/
216 
220 static ADI_CRC_INFO crc_device_info[ADI_CRC_NUM_DEVICES] =
221 {
222  { pADI_CRC0, NULL } /* CRC 0 */
223 };
224 
225 /*============== M O R E D E F I N E S ===============*/
226 
228 #define ADI_CRC_INVALID_HANDLE(h) ((NULL == (h)) || (crc_device_info[0].hDevice != (h)))
229 
231 #define ADI_CRC_DEVICE_IN_USE(DEVNUM) ((NULL) != crc_device_info[(DEVNUM)].hDevice)
232 
233 #ifdef ADI_DEBUG
234 #define HDL_TO_DEVICE_PTR(HDL) ((ADI_CRC_INVALID_HANDLE(HDL)) ? (NULL) : ((ADI_CRC_DEVICE*) (HDL)))
235 #else
236 #define HDL_TO_DEVICE_PTR(HDL) ((ADI_CRC_DEVICE*) (HDL))
237 #endif
238 
239 /*============= C O D E =============*/
240 
241 #if (ADI_CRC_NUM_DEVICES!=1u)
242 #error "!!! Current CRC driver implementation can deal with a unique CRC instance !!!"
243 #endif
244 
245 /*============= L O C A L F U N C T I O N S =============*/
246 
247 /* Prototypes for static functions (required by MISRA-C:2004 Rule 8.1) */
248 
249 static ADI_CRC_INFO *crc_DeviceInfo(ADI_CRC_HANDLE hDevice);
250 
251 static void crc_ResetRegisters (ADI_CRC_DEVICE *pDevice);
252 
253 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT == 0)
254 
255 /* Functions specific to core driven CRC operations */
256 
257 static ADI_CRC_RESULT crc_ExecuteCoreDrivenOperation (ADI_CRC_DEVICE *pDevice, void *pCrcBuf, uint32_t NumBytes, uint32_t NumBits);
258 
259 #else
260 
261 /* Functions specific to DMA driven CRC operations */
262 
263 static ADI_CRC_RESULT crc_ExecuteDmaDrivenOperation(ADI_CRC_DEVICE *pDevice, void *pCrcBuf, uint32_t NumBytes, uint32_t NumBits);
264 static void crc_CalculateCrcForRemaining(ADI_CRC_DEVICE *pDevice, uint8_t *pData, uint32_t NumBytes, uint32_t NumBits);
265 static void CRC_Callback_For_DMA_Err_Int_Handler(void *pcbparam, uint32_t nEvent, void *pArg);
266 void ADI_DMA_CRC_ISR(void);
267 
268 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
269 
270 
280 static ADI_CRC_INFO *crc_DeviceInfo(ADI_CRC_HANDLE hDevice)
281 {
282  ADI_CRC_INFO *pCrcInfo = (ADI_CRC_INVALID_HANDLE(hDevice))
283  ? NULL
284  : (&(crc_device_info[0]));
285  return pCrcInfo;
286 }
287 
288 
298 static void crc_ResetRegisters(ADI_CRC_DEVICE *pDevice)
299 {
300  /* Cast the values to be assigned to the targetted types */
301  const uint32_t byte_mirroring_val = (uint32_t) ADI_CFG_CRC_ENABLE_BYTE_MIRRORING;
302  const uint32_t byte_mirroring_pos = (uint32_t) BITP_CRC_CTL_BYTMIRR;
303  const uint32_t bit_mirroring_val = (uint32_t) ADI_CFG_CRC_ENABLE_BIT_MIRRORING;
304  const uint32_t bit_mirroring_pos = (uint32_t) BITP_CRC_CTL_BITMIRR;
305  const uint32_t seed_value = (uint32_t) ADI_CFG_CRC_SEED_VALUE;
306  const uint32_t polynomial = (uint32_t) ADI_CFG_CRC_POLYNOMIAL;
307 
308  /* Set byte mirroring and bit mirroring in CTL register as configured */
309  pDevice->pReg->CTL = ( (byte_mirroring_val << byte_mirroring_pos)
310  | (bit_mirroring_val << bit_mirroring_pos)
311  );
312  pDevice->pReg->RESULT = seed_value;
313  pDevice->pReg->POLY = polynomial;
314 }
315 
316 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT == 0)
317 
318 /*
319  * @brief Starts core driven CRC operation.
320  *
321  * @param [in] pDevice Pointer to CRC device
322  * @param [in] pCrcBuf Address of data buffer.
323  * @param [in] NumBytes Number of bytes in data buffer.
324  * @param [in] NumBits Number of bits, 0 to 7, in the last partial byte
325  * in CRC data buffer
326  *
327  * @return Status
328  * - ADI_CRC_SUCCESS: Successfully set expected CRC result.
329  */
330 static ADI_CRC_RESULT crc_ExecuteCoreDrivenOperation(
331  ADI_CRC_DEVICE *pDevice,
332  void *pCrcBuf,
333  uint32_t NumBytes,
334  uint32_t NumBits)
335 {
337  uint8_t *pData = (uint8_t *)pCrcBuf; /* initialize the pointer to data to the start of the data buffer */
338  uint32_t lsbFirst = pDevice->pReg->CTL & BITM_CRC_CTL_LSBFIRST;
339 
340  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN);
342  if (((uint32_t)pData & 0x3u) != 0u) /* If the buffer is not 4-byte aligned */
343  {
344  /* feed the CRC byte per byte as long as there are data in the input buffer AND
345  * the data left in the buffer are not 4-byte aligned */
346  while ((NumBytes > 0u) && (((uint32_t)pData & 0x3u) != 0u))
347  {
348  pDevice->pReg->IPBYTE = *pData; /* feed the CRC with the first byte in the buffer */
349  pData++; /* get the next byte to feed into CRC */
350  NumBytes--; /* decrease the number of bytes to be processed */
351  }
352  }
353 
354  /* data left in the input buffer are now 4-byte aligned */
355 
356  while (NumBytes >= 4u) /* if the number of bytes left is greater than 4 bytes */
357  { /* feed CRC peripheral with 4-byte data */
358  uint32_t nData; /* 32-bit variable to be used to feed the CRC peripheral */
359 
360  /*
361  * Here we assume memory is little endian. We need change the following
362  * code if we produce a Cortex-M processor with big endian memory.
363  */
364  if (lsbFirst != 0u)
365  {
366  nData = pData[3];
367  nData = (nData << 8) | pData[2];
368  nData = (nData << 8) | pData[1];
369  nData = (nData << 8) | pData[0];
370  }
371  else
372  {
373  nData = pData[0];
374  nData = (nData << 8) | pData[1];
375  nData = (nData << 8) | pData[2];
376  nData = (nData << 8) | pData[3];
377  }
378  pDevice->pReg->IPDATA = nData; /* feed the CRC peripheral with 32-bit data input */
379  pData += 4; /* move the data pointer in the data buffer */
380  NumBytes -= 4u; /* decrease the number of data to be processed */
381  }
382 
383  while (NumBytes > 0u) /* if the number of data left in the input buffer is smaller than 4 */
384  {
385  pDevice->pReg->IPBYTE = *pData; /* feed the CRC peripheral with the remaining bytes */
386  pData++; /* move the pointer to the next byte in input data buffer */
387  NumBytes--; /* decrease the number of data to be fed into the CRC peripheral */
388  }
389 
390  if (NumBits > 0u) /* if the last byte is a partial byte containing less than 8 bits */
391  {
392  pDevice->pReg->IPBITS[NumBits] = *pData;/* feed the CRC peripheral with the remaining bits (use IPBITS[N] to feed N bits) */
393  }
394 
395  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_EN); /* All the data have been fed into the CRC peripheral : disable it */
396  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* CRC back in idle state */
397  return result;
398 }
399 
400 #else /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
401 
416 static ADI_CRC_RESULT crc_ExecuteDmaDrivenOperation(
417  ADI_CRC_DEVICE *pDevice,
418  void *pCrcBuf,
419  uint32_t NumBytes,
420  uint32_t NumBits)
421 {
423  uint8_t *pData = (uint8_t *)pCrcBuf;
424  bool bUseDma = false; /* assume core driven CRC by default */
425 
426 #ifdef ADI_DEBUG
427  if (!ADI_CRC_VALID_DMA_CHANNEL(ADI_CFG_CRC_DMA_CHANNEL))
428  {
429  /* Report error as Memory DMA not open */
431  }
432  else
433 #endif /* ADI_DEBUG */
434  {
435  /* If LSBFIRST, it's easy. */
436  if ((pDevice->pReg->CTL & BITM_CRC_CTL_LSBFIRST) != 0u)
437  {
438  /* If the buffer is not 4-byte aligned */
439  if (((uint32_t)pData & 0x3u) != 0u)
440  {
441  /* process the first bytes until a 4-byte aligned data location is reached */
442  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN); /* enable CRC */
443  while ((NumBytes > 0u) && (((uint32_t)pData & 0x3u) != 0u))
444  {
445  pDevice->pReg->IPBYTE = *pData; /* feed byte into CRC */
446  pData++; /* get to the next byte */
447  NumBytes--; /* decrease the number of bytes still to be processed */
448  }
449  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_EN); /* disable CRC */
450  }
451 
452  /* 4-byte aligned data transfer */
453  if (NumBytes >= 4u)
454  {
455  /* there are enough data for kicking off a DMA driven CRC operation */
456  const uint32_t channelId = (uint32_t) ADI_CFG_CRC_DMA_CHANNEL;
457  const uint32_t channelBit = 1ul << channelId; /* get a value with the bit set at position identified by channelId */
458  const uint32_t numData = NumBytes / 4u; /* number of 4-byte data to be transferred */
459  const uint32_t src = (uint32_t) pData; /* DMA source address */
460  const uint32_t dst = (uint32_t) &pDevice->pReg->IPDATA; /* destination is CRC IPDATA 32-bit register */
461  const uint32_t numTransData = ( (numData > DMA_TRANSFER_LIMIT)
462  ? DMA_TRANSFER_LIMIT
463  : numData
464  );
465  const uint32_t numTransBytes = (numTransData << 2u);
466  const uint32_t lastDataPos = (numTransBytes - 4u); /* position of last 32-bit data to be transferred in current DMA request */
467 
468  pDevice->pReg->CTL |= ((uint32_t) BITM_CRC_CTL_EN); /* enable CRC (leave other bits unmodified) */
469 
470  pADI_DMA0->EN_SET = channelBit; /* Enable the channel */
471  pADI_DMA0->ALT_CLR = channelBit; /* Set the primary as the current DMA descriptor */
472  pADI_DMA0->SRCADDR_CLR = channelBit; /* Ensure decrement for source is cleared */
473  pADI_DMA0->DSTADDR_CLR = channelBit; /* Ensure decrement for destination is cleared */
474 
475  pPrimaryCCD[channelId].DMADSTEND = dst; /* destination is CRC IPDATA 32-bit register */
476  pPrimaryCCD[channelId].DMASRCEND = src + lastDataPos; /* source end address */
477 
478  pPrimaryCCD[channelId].DMACDC =
479  ( (((uint32_t) ADI_DMA_INCR_NONE) << ((uint32_t) DMA_BITP_CTL_DST_INC)) /* destination address not incremented */
480  | (((uint32_t) ADI_DMA_INCR_4_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_INC)) /* source address incremented by 4 bytes */
481  | (((uint32_t) ADI_DMA_WIDTH_4_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_SIZE)) /* source data size is 4-byte */
482  | ((numTransData - 1u) << ((uint32_t) DMA_BITP_CTL_N_MINUS_1))/* number of DMA transfers (minus 1) */
483  | (DMA_ENUM_CTL_CYCLE_CTL_AUTO_REQ << DMA_BITP_CTL_CYCLE_CTL) /* DMA Auto Request transmission */
484  );
485  pDevice->pRemainingData = (void*)(src + numTransBytes); /* remaining data start address */
486  pDevice->RemainingBytes = NumBytes - numTransBytes; /* remaining bytes that cannot be processed in this DMA batch */
487  pDevice->RemainingBits = NumBits; /* remaining bits if last byte is a partial byte */
488  bUseDma = true; /* there are enough data to run 4-byte DMA transfers to CRC */
489  }
490  }
491  /*
492  * If ! LSBFIRST, we need the DMA controller support byte swap for fixed destination address.
493  * But we don't have such luck, although it supports byte swap for fixed source address.
494  * So we have to set DMA size to one byte, which is slower.
495  *
496  * Another option is using mirroring feature of CRC unit, which would be more complicated.
497  */
498  else
499  {
500  if (NumBytes > 0u)
501  {
509  const uint32_t channelId = (uint32_t) ADI_CFG_CRC_DMA_CHANNEL;
510  const uint32_t channelBit = 1ul << channelId; /* get a value with the bit set at position identified by channelId */
511  const uint32_t src = (uint32_t) pData; /* DMA source address */
512  const uint32_t dst = (uint32_t) &pDevice->pReg->IPBYTE; /* destination is CRC IPBYTE 8-bit register */
513  const uint32_t numTransData = ( (NumBytes > DMA_TRANSFER_LIMIT)
514  ? DMA_TRANSFER_LIMIT
515  : NumBytes
516  );
517  const uint32_t lastDataPos = (numTransData - 1u); /* position of last data to be transferred in buffer */
518 
519  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN); /* enable CRC (leave other bits unmodified) */
520 
521  pADI_DMA0->EN_SET = channelBit; /* Enable the channel */
522  pADI_DMA0->ALT_CLR = channelBit; /* Set the primary as the current DMA descriptor */
523  pADI_DMA0->SRCADDR_CLR = channelBit; /* Ensure decrement for source is cleared */
524  pADI_DMA0->DSTADDR_CLR = channelBit; /* Ensure decrement for destination is cleared */
525 
526  pPrimaryCCD[channelId].DMADSTEND = dst; /* destination is CRC IPBYTE 8-bit register */
527  pPrimaryCCD[channelId].DMASRCEND = src + lastDataPos; /* source end address */
528  pPrimaryCCD[channelId].DMACDC =
529  ( (((uint32_t) ADI_DMA_INCR_NONE) << ((uint32_t) DMA_BITP_CTL_DST_INC)) /* destination address not incremented */
530  | (((uint32_t) ADI_DMA_INCR_1_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_INC)) /* source address incremented by 1 byte */
531  | (((uint32_t) ADI_DMA_WIDTH_1_BYTE) << ((uint32_t) DMA_BITP_CTL_SRC_SIZE)) /* source data size is 1-byte */
532  | ((numTransData - 1u) << ((uint32_t) DMA_BITP_CTL_N_MINUS_1))/* number of DMA transfers (minus 1) */
533  | (DMA_ENUM_CTL_CYCLE_CTL_AUTO_REQ << DMA_BITP_CTL_CYCLE_CTL) /* DMA Auto Request transmission */
534  );
535  pDevice->pRemainingData = (void*) (src + numTransData); /* remaining data start address */
536  pDevice->RemainingBytes = NumBytes - numTransData; /* remaining bytes */
537  pDevice->RemainingBits = NumBits; /* remaining bits if last byte is a partial byte */
538  bUseDma = true; /* there are enough data to run 4-byte DMA transfers to CRC */
539  }
540  }
541 
542  /* if we are in a position to use the DMA to transfer data to the CRC */
543  if (bUseDma== true)
544  {
545  const uint32_t channelId = (uint32_t) ADI_CFG_CRC_DMA_CHANNEL;
546  const uint32_t channelBit = 1ul << channelId; /* get a value with the bit set at position identified by channelId */
547  pADI_DMA0->SWREQ = channelBit; /* Issue a software DMA request */
548  }
549  else
550  {
551  pDevice->pReg->CTL |= (BITM_CRC_CTL_EN);
552  crc_CalculateCrcForRemaining(pDevice, pData, NumBytes, NumBits);
553  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_EN);
554  if(pDevice->pfCallback != NULL)
555  {
556  pDevice->pfCallback(pDevice->pCBParam, (uint32_t) ADI_CRC_EVENT_BUFFER_PROCESSED, pData);
557  }
558  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* CRC calculation completed */
559  }
560  }
561  return result;
562 }
563 
574 static void crc_CalculateCrcForRemaining(ADI_CRC_DEVICE *pDevice, uint8_t *pData, uint32_t NumBytes, uint32_t NumBits)
575 {
576  /* process the remaining bytes */
577  while (NumBytes > 0u)
578  {
579  pDevice->pReg->IPBYTE = *pData;
580  pData++;
581  NumBytes--;
582  }
583 
584  /* process the remaining bits in the last byte if the number of bits is smaller than 8 */
585  if (NumBits > 0u)
586  {
587  pDevice->pReg->IPBITS[NumBits] = *pData;
588  }
589 }
590 
597 static void CRC_Callback_For_DMA_Err_Int_Handler(void *pcbparam, uint32_t nEvent, void *pArg)
598 {
599  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(pcbparam);
600 
601  if (NULL != pDevice)
602  {
603  /* DMA error detected */
604  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* mark the CRC peripheral as IDLE */
605  pDevice->pReg->CTL &= (uint32_t)(~(BITM_CRC_CTL_EN)); /* disable CRC peripheral */
606  }
607 }
608 
617 void ADI_DMA_CRC_ISR(void)
618 {
619  ISR_PROLOG();
620 
621  if (ADI_CRC_DEVICE_IN_USE(0))
622  {
623  ADI_CRC_DEVICE * pDevice = HDL_TO_DEVICE_PTR(crc_device_info[0].hDevice);
624  if (NULL != pDevice)
625  {
626  uint8_t *pData = (uint8_t *)(pDevice->pRemainingData);
627  uint32_t NumBytes = pDevice->RemainingBytes;
628  uint32_t NumBits = pDevice->RemainingBits;
629  bool finishing = (NumBytes < 4u);
630 
631  if (!finishing)
632  {
633  /* there's enough data left for another DMA transfer */
634  ADI_CRC_RESULT result = pDevice->pfSubmitBuffer(pDevice, pData, NumBytes, NumBits);
635  if (ADI_CRC_SUCCESS != result)
636  {
637  /* buffer submission failed: complete the task through core driven operations */
638  finishing = true;
639  }
640  }
641 
642  if (finishing)
643  {
644  /* There are a very few bytes/bits left to be processed or
645  * a DMA transfer request could not be sent */
646  crc_CalculateCrcForRemaining(pDevice, pData, NumBytes, NumBits);
647 
648  /* if a callback function is registered with the interrupt handler
649  * associated with the software DMA channel driving the CRC */
650  if(pDevice->pfCallback != NULL)
651  {
652  pDevice->pfCallback(pDevice->pCBParam, (uint32_t) ADI_CRC_EVENT_BUFFER_PROCESSED, NULL);
653  }
654  pDevice->eCrcOpStatus = ADI_CRC_OP_IDLE; /* CRC back in idle state */
655 
656  }
657  }
658  }
659 
660 #if defined(ADI_CYCLECOUNT_CRC_ISR_ENABLED) && (ADI_CYCLECOUNT_CRC_ISR_ENABLED == 1u)
662 #endif
663 
664  ISR_EPILOG();
665 }
666 
667 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
668 
671 /*============= P U B L I C F U N C T I O N S =============*/
672 
693  uint32_t DeviceNum,
694  void *pMemory,
695  uint32_t MemorySize,
696  ADI_CRC_HANDLE *phDevice)
697 {
699  ADI_CRC_DEVICE *pDevice = (ADI_CRC_DEVICE*) pMemory;/* memory block to be used to manage a CRC driver instance */
700 
701 #ifdef ADI_DEBUG /* IF (Debug information enabled) */
702  if (!ADI_CRC_VALID_DEVICE_ID(DeviceNum)) /* IF (This is not a valid CRC device number) */
703  {
704  result = ADI_CRC_BAD_DEVICE_NUMBER; /* Report failure as bad device number */
705  }
706  else if (ADI_CRC_DEVICE_IN_USE(DeviceNum)) /* IF (The device is in use) */
707  {
708  result = ADI_CRC_IN_USE; /* return CRC Device in use error */
709  }
710  else if ( (MemorySize < ADI_CRC_MEMORY_SIZE) /* IF (Supplied memory size is insufficient) */
711  || (ADI_CRC_MEMORY_SIZE < sizeof(ADI_CRC_DEVICE))
712  )
713  {
714  result = ADI_CRC_INSUFFICIENT_MEMORY; /* Report failure as insufficient memory */
715  }
716  else
717 #endif /* ADI_DEBUG */
718  {
719  /* check that ADI_CRC_MEMORY_SIZE is accurately defined */
720  assert(ADI_CRC_MEMORY_SIZE == sizeof(ADI_CRC_DEVICE));
721 
722  memset(pMemory, 0, MemorySize); /* Clear the given memory */
723 
724  ADI_INT_STATUS_ALLOC();
725  ADI_ENTER_CRITICAL_REGION(); /* Entering critical region, disable interrupts */
726 
727  /* Save the supplied device memory address */
728  crc_device_info[DeviceNum].hDevice = (ADI_CRC_HANDLE)pDevice;
729  pDevice->pReg = crc_device_info[DeviceNum].pReg;
730 
731  ADI_EXIT_CRITICAL_REGION(); /* Re-enable interrupts */
732 
733  crc_ResetRegisters(pDevice); /* Reset CRC registers */
734  *phDevice = crc_device_info[DeviceNum].hDevice; /* Pass a valid handle to this CRC device */
735 
736 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT == 0)
737 
738  pDevice->pfSubmitBuffer = &crc_ExecuteCoreDrivenOperation;
739 
740 #else /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
741 
742  pDevice->pfSubmitBuffer = &crc_ExecuteDmaDrivenOperation;
743  adi_dma_Init();
744 
745  /* Register CRC DMA callback */
746 #ifdef ADI_DEBUG /* IF (Debug information enabled) */
747  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,CRC_Callback_For_DMA_Err_Int_Handler,pDevice))
748  {
749  result = ADI_CRC_FAILURE;
750  }
751 #else
752  adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,CRC_Callback_For_DMA_Err_Int_Handler,pDevice);
753 #endif
754  NVIC_EnableIRQ(ADI_CRC_IRQ_ID); /* Enable the interrupt for the DMA channel used by CRC */
755 #endif /* ADI_CRC_CFG_ENABLE_DMA_SUPPORT */
756  }
757  return result;
758 }
759 
771 {
773  ADI_CRC_INFO *pCrcInfo = crc_DeviceInfo(hDevice); /* get CRC info pointer from CRC handle */
774 #ifdef ADI_DEBUG
775  if (NULL == pCrcInfo)
776  {
777  result = ADI_CRC_BAD_HANDLE; /* invalid CRC handle being used */
778  }
779  else
780 #endif
781  {
782 #if (ADI_CRC_CFG_ENABLE_DMA_SUPPORT != 0)
783  NVIC_DisableIRQ(ADI_CRC_IRQ_ID); /* Disable the interrupt for the DMA channel used by CRC. */
784  /* Register CRC DMA callback */
785 #ifdef ADI_DEBUG /* IF (Debug information enabled) */
786  if (ADI_DMA_SUCCESS != adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,NULL,NULL))
787  {
788  result = ADI_CRC_FAILURE;
789  }
790 #else
791  adi_dma_RegisterCallback(ADI_CFG_CRC_DMA_CHANNEL,NULL,NULL);
792 #endif
793 #endif
794  pCrcInfo->hDevice = NULL; /* Mark CRC driver as closed */
795  }
796  return result;
797 }
815 ADI_CRC_RESULT adi_crc_SetBitMirroring(ADI_CRC_HANDLE const hDevice, const bool bEnable)
816 {
818  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice); /* get CRC device pointer from CRC handle */
819 
820 #ifdef ADI_DEBUG
821  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
822  {
823  result = ADI_CRC_BAD_HANDLE;
824  }
825  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
826  {
827  result = ADI_CRC_FN_NOT_PERMITTED; /* Function not permitted when CRC operation is in progress */
828  }
829  else
830 #endif
831  if(bEnable == true)
832  {
833  pDevice->pReg->CTL |= (BITM_CRC_CTL_BITMIRR); /* enable bit mirroring */
834  }
835  else
836  {
837  pDevice->pReg->CTL &= (uint32_t)(~(BITM_CRC_CTL_BITMIRR)); /* disable bit mirroring */
838  }
839  return result;
840 }
858 ADI_CRC_RESULT adi_crc_SetByteMirroring(ADI_CRC_HANDLE const hDevice, const bool bEnable)
859 {
861  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice); /* get CRC device pointer from CRC handle */
862 
863 #ifdef ADI_DEBUG
864  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
865  {
866  result = ADI_CRC_BAD_HANDLE;
867  }
868  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
869  {
870  result = ADI_CRC_FN_NOT_PERMITTED; /* Function not permitted when CRC operation is in progress */
871  }
872  else
873 #endif
874  if(bEnable == true)
875  {
876  pDevice->pReg->CTL |= (BITM_CRC_CTL_BYTMIRR); /* enable byte mirroring */
877  }
878  else
879  {
880  pDevice->pReg->CTL &= (uint32_t)(~(BITM_CRC_CTL_BYTMIRR)); /* disable byte mirroring */
881  }
882  return result;
883 }
884 
903 ADI_CRC_RESULT adi_crc_SetLSBFirst(ADI_CRC_HANDLE const hDevice, const bool bEnable)
904 {
906  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice); /* get CRC device pointer from CRC handle */
907 
908 #ifdef ADI_DEBUG
909  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
910  {
911  result = ADI_CRC_BAD_HANDLE;
912  }
913  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
914  {
915  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
916  }
917  else
918 #endif
919  if(bEnable == true)
920  {
921  pDevice->pReg->CTL |= (BITM_CRC_CTL_LSBFIRST); /* enable LSB first (MSB first disable) */
922  }
923  else
924  {
925  pDevice->pReg->CTL &= ~(BITM_CRC_CTL_LSBFIRST); /* disable LSB first (MSB first enable) */
926  }
927  return result;
928 }
946 ADI_CRC_RESULT adi_crc_EnableWordSwap(ADI_CRC_HANDLE const hDevice, const bool bEnable)
947 {
949  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
950 
951 #ifdef ADI_DEBUG
952  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
953  {
954  result = ADI_CRC_BAD_HANDLE;
955  }
956  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
957  {
958  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
959  }
960  else
961 #endif
962  if(bEnable == true)
963  {
964  pDevice->pReg->CTL |= BITM_CRC_CTL_W16SWP; /* enable word swap */
965  }
966  else
967  {
968  pDevice->pReg->CTL &= ~BITM_CRC_CTL_W16SWP; /* disable word swap */
969  }
970 
971  return result;
972 }
986  ADI_CRC_HANDLE const hDevice,
987  uint32_t CrcSeedVal)
988 {
990  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
991 
992 #ifdef ADI_DEBUG
993  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
994  {
995  result = ADI_CRC_BAD_HANDLE;
996  }
997  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
998  {
999  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
1000  }
1001  else
1002 #endif /* ADI_DEBUG */
1003  {
1004  pDevice->pReg->RESULT = CrcSeedVal; /* Load the CRC seed value */
1005  }
1006  return result;
1007 }
1008 
1022  ADI_CRC_HANDLE const hDevice,
1023  uint32_t PolynomialVal)
1024 {
1026  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1027 
1028 #ifdef ADI_DEBUG
1029  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1030  {
1031  result = ADI_CRC_BAD_HANDLE;
1032  }
1033  else if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
1034  {
1035  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
1036  }
1037  else
1038 #endif /* ADI_DEBUG */
1039  {
1040  pDevice->pReg->POLY = PolynomialVal; /* Load Polynomial value */
1041  }
1042  return result;
1043 }
1044 
1069  ADI_CRC_HANDLE const hDevice,
1070  void *pCrcBuf,
1071  uint32_t NumBytes,
1072  uint32_t NumBits)
1073 {
1075  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1076 #ifdef ADI_DEBUG
1077  if (NumBits >= 8u)
1078  {
1079  result = ADI_CRC_INVALID_PARAMETER;
1080  }
1081  else if (NULL == pDevice)
1082  {
1083  result = ADI_CRC_BAD_HANDLE;
1084  }
1085  else if (((pDevice->pReg->CTL & BITM_CRC_CTL_REVID) == 0u) && (NumBits != 0u))
1086  {
1087  result = ADI_CRC_FN_NOT_SUPPORTED; /* Partial byte needs CRC unit revision 1 or up */
1088  }
1089  else
1090  if (!ADI_CRC_DEVICE_IS_IDLE(pDevice)) /* IF (CRC in progress) */
1091  {
1092  result = ADI_CRC_FN_NOT_PERMITTED; /* function not permitted when CRC operation is in progress */
1093  }
1094  else
1095 #endif /* ADI_DEBUG */
1096  {
1097  pDevice->eCrcOpStatus = ADI_CRC_OP_IN_PROGRESS; /* mark the CRC as in progress */
1098  result = pDevice->pfSubmitBuffer(pDevice, pCrcBuf, NumBytes, NumBits);
1099 
1100  /* CRC returns in IDLE mode when it has processed all its data, not after submitting a request */
1101  }
1102  return result;
1103 }
1104 
1120  ADI_CRC_HANDLE const hDevice,
1121  bool *pbCrcInProgress)
1122 {
1124  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1125 
1126 #ifdef ADI_DEBUG
1127  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1128  {
1129  result = ADI_CRC_BAD_HANDLE;
1130  }
1131  else
1132 #endif /* ADI_DEBUG */
1133  {
1134 
1135  if ((pDevice)->eCrcOpStatus == ADI_CRC_OP_IN_PROGRESS)
1136  {
1137  *pbCrcInProgress = true;
1138 
1139  }
1140  else
1141  {
1142  *pbCrcInProgress = false;
1143 
1144  }
1145  }
1146  return result;
1147 }
1148 
1171  ADI_CRC_HANDLE const hDevice,
1172  uint32_t *pFinalCrcVal)
1173 {
1175  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1176 
1177 #ifdef ADI_DEBUG
1178  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1179  {
1180  result = ADI_CRC_BAD_HANDLE;
1181  }
1182  else
1183 #endif /* ADI_DEBUG */
1184  {
1185  const uint32_t seed_value = (uint32_t) ADI_CFG_CRC_SEED_VALUE;
1186  *pFinalCrcVal = pDevice->pReg->RESULT; /* Get the final CRC result */
1187  pDevice->pReg->RESULT = seed_value;
1188  }
1189  return result;
1190 }
1191 
1204  ADI_CRC_HANDLE const hDevice,
1205  uint32_t *pCurrentCrcVal)
1206 {
1208  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1209 
1210 #ifdef ADI_DEBUG
1211  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1212  {
1213  result = ADI_CRC_BAD_HANDLE;
1214  }
1215  else
1216 #endif /* ADI_DEBUG */
1217  {
1218  *pCurrentCrcVal = pDevice->pReg->RESULT; /* Get the current CRC result */
1219  }
1220 
1221  return result;
1222 }
1223 
1250  ADI_CRC_HANDLE const hDevice,
1251  ADI_CALLBACK pfCallback,
1252  void *const pCBParam)
1253 {
1255  ADI_CRC_DEVICE *pDevice = HDL_TO_DEVICE_PTR(hDevice);
1256 
1257  ADI_INT_STATUS_ALLOC();
1258  ADI_ENTER_CRITICAL_REGION(); /* Entering critical region, disable interrupts */
1259 
1260 #ifdef ADI_DEBUG
1261  if (NULL == pDevice) /* IF (CRC device handle is invalid) */
1262  {
1263  result = ADI_CRC_BAD_HANDLE;
1264  }
1265  else
1266 #endif /* ADI_DEBUG */
1267  {
1268  /* Update CRC Callback information */
1269  pDevice->pfCallback = pfCallback;
1270  pDevice->pCBParam = pCBParam;
1271  }
1272 
1273  ADI_EXIT_CRITICAL_REGION(); /* Re-enable interrupts */
1274 
1275  return result;
1276 }
1277 
1278 
1279 /*****/
1280 
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_CRC_SEED_VALUE
struct __ADI_CRC_DEVICE * ADI_CRC_HANDLE
Definition: adi_crc.h:144
#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:1203
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:1249
#define ADI_CRC_MEMORY_SIZE
Definition: adi_crc.h:92
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:858
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:1021
ADI_CRC_RESULT adi_crc_SetLSBFirst(ADI_CRC_HANDLE const hDevice, const bool bEnable)
Enable the LSB first.
Definition: adi_crc.c:903
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:692
ADI_CRC_RESULT adi_crc_IsCrcInProgress(ADI_CRC_HANDLE const hDevice, bool *pbCrcInProgress)
Gets the current CRC peripheral status.
Definition: adi_crc.c:1119
ADI_CRC_RESULT
Definition: adi_crc.h:149
ADI_CRC_RESULT adi_crc_Close(ADI_CRC_HANDLE const hDevice)
Closes CRC device instance opened for use.
Definition: adi_crc.c:770
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:1170
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:946
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:985
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:1068
#define ADI_CFG_CRC_ENABLE_BIT_MIRRORING
void adi_dma_Init(void)
Initialize the DMA peripheral.
Definition: adi_dma.c:175
#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.e. when no data are being processd by the CRC.
Definition: adi_crc.c:815