This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Isn't NRF_RNG->EVENTS_VALRDY an event you can wait for with __WFE()?

I've been messing about with the random number generator just testing out events and interrupts. I got it working generating an interrupt but then I thought, NRF_RNG->EVENTS_VALRDY is an event, why not just wait for that instead of messing about with interrupts.

So I tried the following

uint32_t count = 0;
uint32_t wfes  = 0;
  
NRF_RNG->EVENTS_VALRDY = 0;
  
NRF_RNG->TASKS_START=1;
while( 1 )
{
   __WFE();
  wfes++;
    
  if( NRF_RNG->EVENTS_VALRDY != 0 )
  {
      count++;
  }

  NRF_RNG->TASKS_STOP  = 1;
  NRF_RNG->TASKS_START = 1;
}

expecting that the VALRDY event would wake from __WFE. The TASKS_STOP and TASKS_START are there to ensure the RNG does generate another number (PAN-28).

However it doesn't work. If I run it for a while and then breakpoint, wfes == 1, so it's had one wake from __WFE(), count is zero, so EVENTS_VALRDY wasn't ready at that time, and that's all it does.

Is NRF_RNG->EVENTS_VALRDY not the right kind of 'event' to wake from WFE()?

There's lots of other ways to do this I know, but I'd like to know why this one doesn't do what I expected.

------update after the suggestion to clear the events each time ------

With the code

  NRF_RNG->EVENTS_VALRDY = 0;
  NRF_RNG->TASKS_START   = 1;

  uint32_t  wfe = 0;
  uint32_t  cnt = 0;

  while( cnt < 200 )
  {
    while( NRF_RNG->EVENTS_VALRDY == 0 )
    {
      __WFE();
      wfe++;
    }

    cnt++;
    NRF_RNG->EVENTS_VALRDY = 0;
  }

it's no better. It hangs on __WFE() and never returns even though the event has occurred. If you break into it in a debugger, that pulls you out of __WFE() and you see that VALRDY is non-zero and it continues and you can single-step it as much as you like, but as soon as you start it running, it goes into WFE() and never comes out. It seems EVENTS_VALRDY doesn't count as an 'Event' for the purposes of WFE.