ADuCM4x50 Device Drivers API Reference Manual  Release 4.0.0.0
adi_rng.c
1 
21 #include <stdlib.h> /* for 'NULL' definition */
22 #include <assert.h>
23 
24 #include <adi_processor.h>
25 #include <drivers/rng/adi_rng.h>
26 #include "adi_rng_def.h"
27 #include <rtos_map/adi_rtos_map.h>
28 
29 #ifdef __ICCARM__
30 /*
31 * IAR MISRA C 2004 error suppressions.
32 *
33 * Pm011 (rule 6.3): Types which specify sign and size should be used
34 * We use bool which is accepted by MISRA but the toolchain does not accept it
35 *
36 * Pm073 (rule 14.7): a function should have a single point of exit
37 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
38 * Multiple returns are used for error handling.
39 *
40 * Pm050 (rule 14.2): a null statement shall only occur on a line by itself
41 * Needed for null expansion of ISR_PROLOG in no-OS case and others.
42 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
43 * The rule makes an exception for memory-mapped register accesses.
44 */
45 #pragma diag_suppress=Pm011,Pm073,Pm143,Pm050
46 #endif /* __ICCARM__ */
47 
48 #if defined(__ADUCM4x50__) || defined(__ADUCM302x__)
49 #define NUM_RNG_DEVICES (1u)
50 #else
51 #error "Unsupported processor"
52 #endif
53 
54 /*============== D A T A ===============*/
55 
59 #ifdef __ICCARM__
60 #pragma diag_suppress=Pm140
61 #endif
62 
63 static ADI_RNG_DEV_TYPE gRNG_Device[NUM_RNG_DEVICES] =
64 {
65  {(ADI_RNG_TypeDef*)pADI_RNG0,NULL} /* RNG0 */
66 };
67 #ifdef __ICCARM__
68 #pragma diag_default=Pm140
69 #endif
70 
71 /* Forward prototypes */
72 void RNG_Int_Handler(void);
73 
75 #ifdef ADI_DEBUG
76 #define ADI_RNG_INVALID_HANDLE(h) (&gRNG_Device[0] != (h))
77 #endif
78 
108  uint32_t const nDeviceNum,
109  void* const pMemory,
110  uint32_t const MemorySize,
111  ADI_RNG_HANDLE* const phDevice
112  )
113 {
114  ADI_RNG_DEV_TYPE *pDevice;
115 
116  /* store a bad handle in case of failure */
117  *phDevice = (ADI_RNG_HANDLE) NULL;
118 
119 #ifdef ADI_DEBUG
120  if (nDeviceNum >= NUM_RNG_DEVICES)
121  {
122  return ADI_RNG_BAD_DEVICE_NUM;
123  }
124 
125  if ((NULL == pMemory) || ( MemorySize < (uint32_t) ADI_RNG_MEMORY_SIZE))
126  {
127  return ADI_RNG_INVALID_PARAM;
128  }
129  assert (ADI_RNG_MEMORY_SIZE == sizeof(ADI_RNG_DEV_DATA_TYPE));
130 #endif
131 
132  /* local pointer to instance data */
133  pDevice = &gRNG_Device[nDeviceNum];
134 
135 #ifdef ADI_DEBUG
136  if (NULL != pDevice->pData)
137  {
139  }
140 #endif
141 
142  /* Set the internal device data */
143  pDevice->pData = pMemory;
144 
145  /* initialize internal device data */
146  pDevice->pData->IRQn = RNG0_EVT_IRQn;
147  pDevice->pData->CBFunc = NULL;
148 
149  /* clear any pending interrupts. Both bits are write 1 to clear */
150  pDevice->pRNG->STAT = BITM_RNG_STAT_RNRDY | BITM_RNG_STAT_STUCK;
151 
152  /* Set the RNG register based on static configuration */
153  pDevice->pRNG->CTL = (uint16_t)RNG0_CFG_ONLY_8_BIT << BITP_RNG_CTL_SINGLE;
154  pDevice->pRNG->LEN = (RNG0_CFG_LENGTH_RELOAD << BITP_RNG_LEN_RELOAD)
155  | (RNG0_CFG_LENGTH_PRESCALER << BITP_RNG_LEN_PRESCALE);
156 
157  /* The interrupt handler only gets used in the case of callback mode so its
158  * enabling only happens in the adi_rng_RegisterCallBack API.
159  */
160  NVIC_ClearPendingIRQ(pDevice->pData->IRQn);
161 
162  /* store handle at application handle pointer */
163  *phDevice = pDevice;
164 
165  return ADI_RNG_SUCCESS;
166 }
167 
168 
184 {
185  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
186 
187 #ifdef ADI_DEBUG
188  if (ADI_RNG_INVALID_HANDLE(pDevice)){
189  return ADI_RNG_BAD_DEV_HANDLE;
190  }
191 
192  if (NULL == pDevice->pData) {
194  }
195 #endif
196 
197  /* uninitialize */
198  NVIC_DisableIRQ(pDevice->pData->IRQn);
199  pDevice->pData = NULL;
200 
201  return ADI_RNG_SUCCESS;
202 }
203 
218 ADI_RNG_RESULT adi_rng_Enable (ADI_RNG_HANDLE const hDevice, bool const bFlag)
219 {
220  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
221  ADI_INT_STATUS_ALLOC();
222 
223 #ifdef ADI_DEBUG
224  if (ADI_RNG_INVALID_HANDLE(pDevice)) {
225  return ADI_RNG_BAD_DEV_HANDLE;
226  }
227 
228  if (NULL == pDevice->pData) {
230  }
231 #endif
232 
233  ADI_ENTER_CRITICAL_REGION();
234  if (true == bFlag) {
235  pDevice->pRNG->CTL |= BITM_RNG_CTL_EN;
236  } else {
237  pDevice->pRNG->CTL &= (uint16_t)~(BITM_RNG_CTL_EN);
238  }
239  ADI_EXIT_CRITICAL_REGION();
240 
241  return ADI_RNG_SUCCESS;
242 }
243 
261 ADI_RNG_RESULT adi_rng_EnableBuffering (ADI_RNG_HANDLE const hDevice, bool const bFlag)
262 {
263  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
264  ADI_INT_STATUS_ALLOC();
265 
266 #ifdef ADI_DEBUG
267  if (ADI_RNG_INVALID_HANDLE(pDevice)) {
268  return ADI_RNG_BAD_DEV_HANDLE;
269  }
270 
271  if (NULL == pDevice->pData) {
273  }
274 #endif
275 
276  ADI_ENTER_CRITICAL_REGION();
277  if (true == bFlag) {
278  pDevice->pRNG->CTL &= (uint16_t)~(BITM_RNG_CTL_SINGLE);
279  } else {
280  pDevice->pRNG->CTL |= BITM_RNG_CTL_SINGLE;
281  }
282  ADI_EXIT_CRITICAL_REGION();
283 
284  return ADI_RNG_SUCCESS;
285 }
286 
304  ADI_RNG_HANDLE const hDevice,
305  uint16_t const nLenPrescaler,
306  uint16_t const nLenReload
307  )
308 {
309  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
310  ADI_INT_STATUS_ALLOC();
311 
312 #ifdef ADI_DEBUG
313  if (ADI_RNG_INVALID_HANDLE(pDevice)){
314  return ADI_RNG_BAD_DEV_HANDLE;
315  }
316 
317  if (NULL == pDevice->pData) {
319  }
320 
321  if ( (nLenPrescaler > 10u)
322  || ((0u == nLenPrescaler) && (0u == nLenReload))
323  || (nLenReload > 4095u)) {
324  return ADI_RNG_INVALID_PARAM;
325  }
326 #endif
327 
328  ADI_ENTER_CRITICAL_REGION();
329  /* Set the sample reload and prescaler value */
330  pDevice->pRNG->LEN = (uint16_t)((uint16_t)(nLenReload << BITP_RNG_LEN_RELOAD) & BITM_RNG_LEN_RELOAD)
331  | (uint16_t)((uint16_t)(nLenPrescaler << BITP_RNG_LEN_PRESCALE) & BITM_RNG_LEN_PRESCALE);
332  ADI_EXIT_CRITICAL_REGION();
333 
334  return ADI_RNG_SUCCESS;
335 }
336 
337 
359 ADI_RNG_RESULT adi_rng_GetRdyStatus (ADI_RNG_HANDLE const hDevice, bool* const pbFlag)
360 {
361  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
362 
363 #ifdef ADI_DEBUG
364  if (ADI_RNG_INVALID_HANDLE(pDevice)){
365  return ADI_RNG_BAD_DEV_HANDLE;
366  }
367 
368  if (NULL == pDevice->pData) {
370  }
371 
372  if (NULL == pbFlag) {
373  return ADI_RNG_INVALID_PARAM;
374  }
375 #endif
376 
377  /* Get the RNG Ready status bit */
378  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) != 0u)
379  {
380  *pbFlag = true;
381  }
382  else
383  {
384  *pbFlag = false;
385  }
386 
387  return ADI_RNG_SUCCESS;
388 }
389 
409  ADI_RNG_HANDLE const hDevice,
410  bool* const pbFlag
411  )
412 {
413  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
414 
415 #ifdef ADI_DEBUG
416  if (ADI_RNG_INVALID_HANDLE(pDevice)){
417  return ADI_RNG_BAD_DEV_HANDLE;
418  }
419 
420  if (pDevice->pData == NULL) {
422  }
423 
424  if (NULL == pbFlag) {
425  return ADI_RNG_INVALID_PARAM;
426  }
427 #endif
428 
429  /* Get the stuck status bit */
430  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_STUCK) != 0u)
431  {
432  *pbFlag = true;
433  }
434  else
435  {
436  *pbFlag = false;
437  }
438 
439  return ADI_RNG_SUCCESS;
440 }
441 
442 
464 ADI_RNG_RESULT adi_rng_GetRngData (ADI_RNG_HANDLE const hDevice, uint32_t* const pRegData)
465 {
466  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
467 
468 #ifdef ADI_DEBUG
469  if (ADI_RNG_INVALID_HANDLE(pDevice)){
470  return ADI_RNG_BAD_DEV_HANDLE;
471  }
472 
473  if (NULL == pDevice->pData) {
475  }
476 
477  if (NULL == pRegData) {
478  return ADI_RNG_INVALID_PARAM;
479  }
480 
481  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) == 0u) {
482  return ADI_RNG_INVALID_STATE;
483  }
484 #endif
485 
486  /* Get the RNG CRC accumulator value */
487  *pRegData = pDevice->pRNG->DATA;
488 
489  return ADI_RNG_SUCCESS;
490 }
491 
492 
509 ADI_RNG_RESULT adi_rng_GetOscCount (ADI_RNG_HANDLE const hDevice, uint32_t* const pOscCount)
510 {
511  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
512 
513 #ifdef ADI_DEBUG
514  if (ADI_RNG_INVALID_HANDLE(pDevice)){
515  return ADI_RNG_BAD_DEV_HANDLE;
516  }
517 
518  if (NULL == pDevice->pData) {
520  }
521 
522  if (NULL == pOscCount) {
523  return (ADI_RNG_INVALID_PARAM);
524  }
525 
526  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) == 0u) {
527  return ADI_RNG_INVALID_STATE;
528  }
529 #endif
530 
531  /* Get the oscillator count high count */
532  *pOscCount = pDevice->pRNG->OSCCNT;
533 
534  return ADI_RNG_SUCCESS;
535 }
536 
556  ADI_RNG_HANDLE const hDevice,
557  uint32_t const nIndex,
558  uint8_t* const pOscDiff
559  )
560 {
561  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
562 
563 #ifdef ADI_DEBUG
564  if (ADI_RNG_INVALID_HANDLE(pDevice)){
565  return ADI_RNG_BAD_DEV_HANDLE;
566  }
567 
568  if (NULL == pDevice->pData) {
570  }
571 
572  if ((NULL == pOscDiff) || (nIndex > 3u)) {
573  return( ADI_RNG_INVALID_PARAM );
574  }
575 
576  if ((pDevice->pRNG->STAT & BITM_RNG_STAT_RNRDY) == 0u) {
577  return ADI_RNG_INVALID_STATE;
578  }
579 #endif
580 
581  /* Get the Osc Difference Register */
582  *pOscDiff = (uint8_t)pDevice->pRNG->OSCDIFF[nIndex];
583 
584  return ADI_RNG_SUCCESS;
585 }
586 
605  ADI_RNG_HANDLE const hDevice,
606  uint16_t* const pLenPrescaler,
607  uint16_t* const pLenReload
608  )
609 {
610  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
611 
612 #ifdef ADI_DEBUG
613  if (ADI_RNG_INVALID_HANDLE(pDevice)){
614  return ADI_RNG_BAD_DEV_HANDLE;
615  }
616 
617  if (NULL == pDevice->pData) {
619  }
620 
621  if ((NULL == pLenPrescaler) || (NULL == pLenReload)) {
622  return ADI_RNG_INVALID_PARAM;
623  }
624 #endif
625 
626  *pLenPrescaler = (pDevice->pRNG->LEN & BITM_RNG_LEN_PRESCALE) >> BITP_RNG_LEN_PRESCALE;
627  *pLenReload = (pDevice->pRNG->LEN & BITM_RNG_LEN_RELOAD) >> BITP_RNG_LEN_RELOAD;
628 
629  return ADI_RNG_SUCCESS;
630 }
631 
632 
633 /*************************************************************************************************
634 **************************************************************************************************
635 ***************************************** CALLBACKS ******************************************
636 ***************************************** AND ******************************************
637 ***************************************** INTERRUPT ******************************************
638 **************************************************************************************************
639 *************************************************************************************************/
640 
641 
678  ADI_RNG_HANDLE hDevice,
679  ADI_CALLBACK cbFunc,
680  void *pCBParam)
681 {
682  ADI_RNG_DEV_TYPE *pDevice = (ADI_RNG_DEV_TYPE*)hDevice;
683 
684 #ifdef ADI_DEBUG
685  if (ADI_RNG_INVALID_HANDLE(pDevice)){
686  return ADI_RNG_BAD_DEV_HANDLE;
687  }
688 
689  if (NULL == pDevice->pData) {
691  }
692 #endif
693 
694  /* save the callback info */
695  pDevice->pData->CBFunc = cbFunc;
696  pDevice->pData->pCBParam = pCBParam;
697 
698  if (NULL != cbFunc) {
699  /* enable RNG interrupts in NVIC */
700  NVIC_EnableIRQ(pDevice->pData->IRQn);
701  } else {
702  NVIC_DisableIRQ(pDevice->pData->IRQn);
703  }
704 
705  return ADI_RNG_SUCCESS;
706 }
707 
709 /* RNG driver interrupt handler. Overrides weak default handler in startup file */
710 void RNG_Int_Handler(void)
711 {
712  ISR_PROLOG();
713  ADI_RNG_DEV_TYPE *pDevice = &gRNG_Device[0];
714  register uint16_t candidate;
715 
716  /* if we have an initialized driver... */
717  if (NULL != pDevice->pData)
718  {
719  /* if we have a registered callback */
720  if (NULL != pDevice->pData->CBFunc)
721  {
722  ADI_INT_STATUS_ALLOC();
723 
724  ADI_ENTER_CRITICAL_REGION();
725  /* read status register without other interrupts in between */
726  candidate = pDevice->pRNG->STAT;
727  ADI_EXIT_CRITICAL_REGION();
728 
729  /* Only have bits in stat that are necessary */
730  candidate = candidate & (BITM_RNG_STAT_STUCK | BITM_RNG_STAT_RNRDY);
731 
732  while (0u != candidate) {
733  uint32_t nEvent;
734 
735  if (0u != (candidate & BITM_RNG_STAT_RNRDY)) {
736  nEvent = ADI_RNG_EVENT_READY;
737  candidate &= (uint16_t)~BITM_RNG_STAT_RNRDY;
738  } else if (0u != (candidate & BITM_RNG_STAT_STUCK)) {
739  nEvent = ADI_RNG_EVENT_STUCK;
740  candidate &= (uint16_t)~BITM_RNG_STAT_STUCK;
741  } else {
742  break;
743  }
744 
745  pDevice->pData->CBFunc (
746  pDevice->pData->pCBParam,
747  nEvent,
748  NULL
749  );
750  }
751 
752  pDevice->pRNG->STAT = BITM_RNG_STAT_RNRDY | BITM_RNG_STAT_STUCK;
753  }
754  }
755  ISR_EPILOG();
756 }
759 /*
760 ** EOF
761 */
762 
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:408
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:509
#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:464
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:555
void * ADI_RNG_HANDLE
Definition: adi_rng.h:76
ADI_RNG_RESULT adi_rng_RegisterCallback(ADI_RNG_HANDLE hDevice, ADI_CALLBACK cbFunc, void *pCBParam)
RNG Application callback registration API.
Definition: adi_rng.c:677
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:604
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:359
ADI_RNG_RESULT adi_rng_EnableBuffering(ADI_RNG_HANDLE const hDevice, bool const bFlag)
Enables/Disables Buffering for RNG.
Definition: adi_rng.c:261
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:303
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:107
ADI_RNG_RESULT adi_rng_Close(ADI_RNG_HANDLE hDevice)
Uninitializes and deallocates the RNG device.
Definition: adi_rng.c:183
#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:218
#define ADI_RNG_MEMORY_SIZE
Definition: adi_rng.h:72
#define RNG0_CFG_LENGTH_PRESCALER
ADI_RNG_RESULT
Definition: adi_rng.h:48