ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_rng.c
1 
54 #include <stdlib.h> /* for 'NULL' definition */
55 #include <assert.h>
56 
57 #include <adi_processor.h>
58 #include <drivers/rng/adi_rng.h>
59 #include "adi_rng_def.h"
60 #include <rtos_map/adi_rtos_map.h>
61 
62 #ifdef __ICCARM__
63 /*
64 * IAR MISRA C 2004 error suppressions.
65 *
66 * Pm011 (rule 6.3): Types which specify sign and size should be used
67 * We use bool which is accepted by MISRA but the toolchain does not accept it
68 *
69 * Pm073 (rule 14.7): a function should have a single point of exit
70 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
71 * Multiple returns are used for error handling.
72 *
73 * Pm050 (rule 14.2): a null statement shall only occur on a line by itself
74 * Needed for null expansion of ISR_PROLOG in no-OS case and others.
75 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
76 * The rule makes an exception for memory-mapped register accesses.
77 */
78 #pragma diag_suppress=Pm011,Pm073,Pm143,Pm050
79 #endif /* __ICCARM__ */
80 
81 #if defined(__ADUCM4x50__) || defined(__ADUCM302x__)
82 #define NUM_RNG_DEVICES (1u)
83 #else
84 #error "Unsupported processor"
85 #endif
86 
87 /*============== D A T A ===============*/
88 
92 #ifdef __ICCARM__
93 #pragma diag_suppress=Pm140
94 #endif
95 
96 static ADI_RNG_DEV_TYPE gRNG_Device[NUM_RNG_DEVICES] =
97 {
98  {(ADI_RNG_TypeDef*)pADI_RNG0,NULL} /* RNG0 */
99 };
100 #ifdef __ICCARM__
101 #pragma diag_default=Pm140
102 #endif
103 
104 /* Forward prototypes */
105 void RNG_Int_Handler(void);
106 
108 #ifdef ADI_DEBUG
109 #define ADI_RNG_INVALID_HANDLE(h) (&gRNG_Device[0] != (h))
110 #endif
111 
141  uint32_t const nDeviceNum,
142  void* const pMemory,
143  uint32_t const MemorySize,
144  ADI_RNG_HANDLE* const phDevice
145  )
146 {
147  ADI_RNG_DEV_TYPE *pDevice;
148 
149  /* store a bad handle in case of failure */
150  *phDevice = (ADI_RNG_HANDLE) NULL;
151 
152 #ifdef ADI_DEBUG
153  if (nDeviceNum >= NUM_RNG_DEVICES)
154  {
155  return ADI_RNG_BAD_DEVICE_NUM;
156  }
157 
158  if ((NULL == pMemory) || ( MemorySize < (uint32_t) ADI_RNG_MEMORY_SIZE))
159  {
160  return ADI_RNG_INVALID_PARAM;
161  }
162  assert (ADI_RNG_MEMORY_SIZE == sizeof(ADI_RNG_DEV_DATA_TYPE));
163 #endif
164 
165  /* local pointer to instance data */
166  pDevice = &gRNG_Device[nDeviceNum];
167 
168 #ifdef ADI_DEBUG
169  if (NULL != pDevice->pData)
170  {
172  }
173 #endif
174 
175  /* Set the internal device data */
176  pDevice->pData = pMemory;
177 
178  /* initialize internal device data */
179  pDevice->pData->IRQn = RNG0_EVT_IRQn;
180  pDevice->pData->CBFunc = NULL;
181 
182  /* clear any pending interrupts. Both bits are write 1 to clear */
183  pDevice->pRNG->STAT = BITM_RNG_STAT_RNRDY | BITM_RNG_STAT_STUCK;
184 
185  /* Set the RNG register based on static configuration */
186  pDevice->pRNG->CTL = (uint16_t)RNG0_CFG_ONLY_8_BIT << BITP_RNG_CTL_SINGLE;
187  pDevice->pRNG->LEN = (RNG0_CFG_LENGTH_RELOAD << BITP_RNG_LEN_RELOAD)
188  | (RNG0_CFG_LENGTH_PRESCALER << BITP_RNG_LEN_PRESCALE);
189 
190  /* The interrupt handler only gets used in the case of callback mode so its
191  * enabling only happens in the adi_rng_RegisterCallBack API.
192  */
193  NVIC_ClearPendingIRQ(pDevice->pData->IRQn);
194 
195  /* store handle at application handle pointer */
196  *phDevice = pDevice;
197 
198  return ADI_RNG_SUCCESS;
199 }
200 
201 
217 {
218  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
219 
220 #ifdef ADI_DEBUG
221  if (ADI_RNG_INVALID_HANDLE(pDevice)){
222  return ADI_RNG_BAD_DEV_HANDLE;
223  }
224 
225  if (NULL == pDevice->pData) {
227  }
228 #endif
229 
230  /* uninitialize */
231  NVIC_DisableIRQ(pDevice->pData->IRQn);
232  pDevice->pData = NULL;
233 
234  return ADI_RNG_SUCCESS;
235 }
236 
251 ADI_RNG_RESULT adi_rng_Enable (ADI_RNG_HANDLE const hDevice, bool const bFlag)
252 {
253  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
254  ADI_INT_STATUS_ALLOC();
255 
256 #ifdef ADI_DEBUG
257  if (ADI_RNG_INVALID_HANDLE(pDevice)) {
258  return ADI_RNG_BAD_DEV_HANDLE;
259  }
260 
261  if (NULL == pDevice->pData) {
263  }
264 #endif
265 
266  ADI_ENTER_CRITICAL_REGION();
267  if (true == bFlag) {
268  pDevice->pRNG->CTL |= BITM_RNG_CTL_EN;
269  } else {
270  pDevice->pRNG->CTL &= (uint16_t)~(BITM_RNG_CTL_EN);
271  }
272  ADI_EXIT_CRITICAL_REGION();
273 
274  return ADI_RNG_SUCCESS;
275 }
276 
294 ADI_RNG_RESULT adi_rng_EnableBuffering (ADI_RNG_HANDLE const hDevice, bool const bFlag)
295 {
296  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
297  ADI_INT_STATUS_ALLOC();
298 
299 #ifdef ADI_DEBUG
300  if (ADI_RNG_INVALID_HANDLE(pDevice)) {
301  return ADI_RNG_BAD_DEV_HANDLE;
302  }
303 
304  if (NULL == pDevice->pData) {
306  }
307 #endif
308 
309  ADI_ENTER_CRITICAL_REGION();
310  if (true == bFlag) {
311  pDevice->pRNG->CTL &= (uint16_t)~(BITM_RNG_CTL_SINGLE);
312  } else {
313  pDevice->pRNG->CTL |= BITM_RNG_CTL_SINGLE;
314  }
315  ADI_EXIT_CRITICAL_REGION();
316 
317  return ADI_RNG_SUCCESS;
318 }
319 
337  ADI_RNG_HANDLE const hDevice,
338  uint16_t const nLenPrescaler,
339  uint16_t const nLenReload
340  )
341 {
342  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
343  ADI_INT_STATUS_ALLOC();
344 
345 #ifdef ADI_DEBUG
346  if (ADI_RNG_INVALID_HANDLE(pDevice)){
347  return ADI_RNG_BAD_DEV_HANDLE;
348  }
349 
350  if (NULL == pDevice->pData) {
352  }
353 
354  if ( (nLenPrescaler > 10u)
355  || ((0u == nLenPrescaler) && (0u == nLenReload))
356  || (nLenReload > 4095u)) {
357  return ADI_RNG_INVALID_PARAM;
358  }
359 #endif
360 
361  ADI_ENTER_CRITICAL_REGION();
362  /* Set the sample reload and prescaler value */
363  pDevice->pRNG->LEN = (uint16_t)((uint16_t)(nLenReload << BITP_RNG_LEN_RELOAD) & BITM_RNG_LEN_RELOAD)
364  | (uint16_t)((uint16_t)(nLenPrescaler << BITP_RNG_LEN_PRESCALE) & BITM_RNG_LEN_PRESCALE);
365  ADI_EXIT_CRITICAL_REGION();
366 
367  return ADI_RNG_SUCCESS;
368 }
369 
370 
392 ADI_RNG_RESULT adi_rng_GetRdyStatus (ADI_RNG_HANDLE const hDevice, bool* const pbFlag)
393 {
394  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
395 
396 #ifdef ADI_DEBUG
397  if (ADI_RNG_INVALID_HANDLE(pDevice)){
398  return ADI_RNG_BAD_DEV_HANDLE;
399  }
400 
401  if (NULL == pDevice->pData) {
403  }
404 
405  if (NULL == pbFlag) {
406  return ADI_RNG_INVALID_PARAM;
407  }
408 #endif
409 
410  /* Get the RNG Ready status bit */
411  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) != 0u)
412  {
413  *pbFlag = true;
414  }
415  else
416  {
417  *pbFlag = false;
418  }
419 
420  return ADI_RNG_SUCCESS;
421 }
422 
442  ADI_RNG_HANDLE const hDevice,
443  bool* const pbFlag
444  )
445 {
446  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
447 
448 #ifdef ADI_DEBUG
449  if (ADI_RNG_INVALID_HANDLE(pDevice)){
450  return ADI_RNG_BAD_DEV_HANDLE;
451  }
452 
453  if (pDevice->pData == NULL) {
455  }
456 
457  if (NULL == pbFlag) {
458  return ADI_RNG_INVALID_PARAM;
459  }
460 #endif
461 
462  /* Get the stuck status bit */
463  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_STUCK) != 0u)
464  {
465  *pbFlag = true;
466  }
467  else
468  {
469  *pbFlag = false;
470  }
471 
472  return ADI_RNG_SUCCESS;
473 }
474 
475 
497 ADI_RNG_RESULT adi_rng_GetRngData (ADI_RNG_HANDLE const hDevice, uint32_t* const pRegData)
498 {
499  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
500 
501 #ifdef ADI_DEBUG
502  if (ADI_RNG_INVALID_HANDLE(pDevice)){
503  return ADI_RNG_BAD_DEV_HANDLE;
504  }
505 
506  if (NULL == pDevice->pData) {
508  }
509 
510  if (NULL == pRegData) {
511  return ADI_RNG_INVALID_PARAM;
512  }
513 
514  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) == 0u) {
515  return ADI_RNG_INVALID_STATE;
516  }
517 #endif
518 
519  /* Get the RNG CRC accumulator value */
520  *pRegData = pDevice->pRNG->DATA;
521 
522  return ADI_RNG_SUCCESS;
523 }
524 
525 
542 ADI_RNG_RESULT adi_rng_GetOscCount (ADI_RNG_HANDLE const hDevice, uint32_t* const pOscCount)
543 {
544  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
545 
546 #ifdef ADI_DEBUG
547  if (ADI_RNG_INVALID_HANDLE(pDevice)){
548  return ADI_RNG_BAD_DEV_HANDLE;
549  }
550 
551  if (NULL == pDevice->pData) {
553  }
554 
555  if (NULL == pOscCount) {
556  return (ADI_RNG_INVALID_PARAM);
557  }
558 
559  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) == 0u) {
560  return ADI_RNG_INVALID_STATE;
561  }
562 #endif
563 
564  /* Get the oscillator count high count */
565  *pOscCount = pDevice->pRNG->OSCCNT;
566 
567  return ADI_RNG_SUCCESS;
568 }
569 
589  ADI_RNG_HANDLE const hDevice,
590  uint32_t const nIndex,
591  uint8_t* const pOscDiff
592  )
593 {
594  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
595 
596 #ifdef ADI_DEBUG
597  if (ADI_RNG_INVALID_HANDLE(pDevice)){
598  return ADI_RNG_BAD_DEV_HANDLE;
599  }
600 
601  if (NULL == pDevice->pData) {
603  }
604 
605  if ((NULL == pOscDiff) || (nIndex > 3u)) {
606  return( ADI_RNG_INVALID_PARAM );
607  }
608 
609  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) == 0u) {
610  return ADI_RNG_INVALID_STATE;
611  }
612 #endif
613 
614  /* Get the Osc Difference Register */
615  *pOscDiff = (uint8_t)pDevice->pRNG->OSCDIFF[nIndex];
616 
617  return ADI_RNG_SUCCESS;
618 }
619 
638  ADI_RNG_HANDLE const hDevice,
639  uint16_t* const pLenPrescaler,
640  uint16_t* const pLenReload
641  )
642 {
643  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
644 
645 #ifdef ADI_DEBUG
646  if (ADI_RNG_INVALID_HANDLE(pDevice)){
647  return ADI_RNG_BAD_DEV_HANDLE;
648  }
649 
650  if (NULL == pDevice->pData) {
652  }
653 
654  if ((NULL == pLenPrescaler) || (NULL == pLenReload)) {
655  return ADI_RNG_INVALID_PARAM;
656  }
657 #endif
658 
659  *pLenPrescaler = (pDevice->pRNG->LEN & BITM_RNG_LEN_PRESCALE) >> BITP_RNG_LEN_PRESCALE;
660  *pLenReload = (pDevice->pRNG->LEN & BITM_RNG_LEN_RELOAD) >> BITP_RNG_LEN_RELOAD;
661 
662  return ADI_RNG_SUCCESS;
663 }
664 
665 
666 /*************************************************************************************************
667 **************************************************************************************************
668 ***************************************** CALLBACKS ******************************************
669 ***************************************** AND ******************************************
670 ***************************************** INTERRUPT ******************************************
671 **************************************************************************************************
672 *************************************************************************************************/
673 
674 
711  ADI_RNG_HANDLE hDevice,
712  ADI_CALLBACK cbFunc,
713  void *pCBParam)
714 {
715  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
716 
717 #ifdef ADI_DEBUG
718  if (ADI_RNG_INVALID_HANDLE(pDevice)){
719  return ADI_RNG_BAD_DEV_HANDLE;
720  }
721 
722  if (NULL == pDevice->pData) {
724  }
725 #endif
726 
727  /* save the callback info */
728  pDevice->pData->CBFunc = cbFunc;
729  pDevice->pData->pCBParam = pCBParam;
730 
731  if (NULL != cbFunc) {
732  /* enable RNG interrupts in NVIC */
733  NVIC_EnableIRQ(pDevice->pData->IRQn);
734  } else {
735  NVIC_DisableIRQ(pDevice->pData->IRQn);
736  }
737 
738  return ADI_RNG_SUCCESS;
739 }
740 
742 /* RNG driver interrupt handler. Overrides weak default handler in startup file */
743 void RNG_Int_Handler(void)
744 {
745  ISR_PROLOG();
746  ADI_RNG_DEV_TYPE *pDevice = &gRNG_Device[0];
747  register uint16_t candidate;
748 
749  /* if we have an initialized driver... */
750  if (NULL != pDevice->pData)
751  {
752  /* if we have a registered callback */
753  if (NULL != pDevice->pData->CBFunc)
754  {
755  ADI_INT_STATUS_ALLOC();
756 
757  ADI_ENTER_CRITICAL_REGION();
758  /* read status register without other interrupts in between */
759  candidate = pDevice->pRNG->STAT;
760  ADI_EXIT_CRITICAL_REGION();
761 
762  /* Only have bits in stat that are necessary */
763  candidate = candidate & (BITM_RNG_STAT_STUCK | BITM_RNG_STAT_RNRDY);
764 
765  while (0u != candidate) {
766  uint32_t nEvent;
767 
768  if (0u != (candidate & BITM_RNG_STAT_RNRDY)) {
769  nEvent = ADI_RNG_EVENT_READY;
770  candidate &= (uint16_t)~BITM_RNG_STAT_RNRDY;
771  } else if (0u != (candidate & BITM_RNG_STAT_STUCK)) {
772  nEvent = ADI_RNG_EVENT_STUCK;
773  candidate &= (uint16_t)~BITM_RNG_STAT_STUCK;
774  } else {
775  break;
776  }
777 
778  pDevice->pData->CBFunc (
779  pDevice->pData->pCBParam,
780  nEvent,
781  NULL
782  );
783  }
784 
785  pDevice->pRNG->STAT = BITM_RNG_STAT_RNRDY | BITM_RNG_STAT_STUCK;
786  }
787  }
788  ISR_EPILOG();
789 }
792 /*
793 ** EOF
794 */
795 
ADI_RNG_RESULT adi_rng_GetStuckStatus(ADI_RNG_HANDLE const hDevice, bool *const pbFlag)
Retrieve whether the RNG oscillator output is stuck at a constant value.
Definition: adi_rng.c:441
ADI_RNG_RESULT adi_rng_GetOscCount(ADI_RNG_HANDLE const hDevice, uint32_t *const pOscCount)
Retrieve the current RNG Oscillator count.
Definition: adi_rng.c:542
#define RNG0_CFG_ONLY_8_BIT
ADI_RNG_RESULT adi_rng_GetRngData(ADI_RNG_HANDLE const hDevice, uint32_t *const pRegData)
Retrieve the current value of the RNG data register.
Definition: adi_rng.c:497
ADI_RNG_RESULT adi_rng_GetOscDiff(ADI_RNG_HANDLE const hDevice, uint32_t const nIndex, uint8_t *const pOscDiff)
Retrieve the current RNG Oscillator difference value for the given index.
Definition: adi_rng.c:588
void * ADI_RNG_HANDLE
Definition: adi_rng.h:108
ADI_RNG_RESULT adi_rng_RegisterCallback(ADI_RNG_HANDLE hDevice, ADI_CALLBACK cbFunc, void *pCBParam)
RNG Application callback registration API.
Definition: adi_rng.c:710
ADI_RNG_RESULT adi_rng_GetSampleLen(ADI_RNG_HANDLE const hDevice, uint16_t *const pLenPrescaler, uint16_t *const pLenReload)
Retrieve the current RNG sample length prescale and reload value configured in the device...
Definition: adi_rng.c:637
ADI_RNG_RESULT adi_rng_GetRdyStatus(ADI_RNG_HANDLE const hDevice, bool *const pbFlag)
Retrieves the current state of RNG data/CRC accumulator register.
Definition: adi_rng.c:392
ADI_RNG_RESULT adi_rng_EnableBuffering(ADI_RNG_HANDLE const hDevice, bool const bFlag)
Enables/Disables Buffering for RNG.
Definition: adi_rng.c:294
ADI_RNG_RESULT adi_rng_SetSampleLen(ADI_RNG_HANDLE const hDevice, uint16_t const nLenPrescaler, uint16_t const nLenReload)
Sets the reload and prescale value for the sample counter. The Sample Length will be nLenReload*2^nLe...
Definition: adi_rng.c:336
ADI_RNG_RESULT adi_rng_Open(uint32_t const nDeviceNum, void *const pMemory, uint32_t const MemorySize, ADI_RNG_HANDLE *const phDevice)
Opena a Random Number Generator Device.
Definition: adi_rng.c:140
ADI_RNG_RESULT adi_rng_Close(ADI_RNG_HANDLE hDevice)
Uninitializes and deallocates the RNG device.
Definition: adi_rng.c:216
#define RNG0_CFG_LENGTH_RELOAD
ADI_RNG_RESULT adi_rng_Enable(ADI_RNG_HANDLE const hDevice, bool const bFlag)
Enables/Disables the RNG device.
Definition: adi_rng.c:251
#define ADI_RNG_MEMORY_SIZE
Definition: adi_rng.h:104
#define RNG0_CFG_LENGTH_PRESCALER
ADI_RNG_RESULT
Definition: adi_rng.h:80