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.

Parents
  • I setup a small project to test this, and you'll need to init a couple of things, as well as clear pending IRQ after the event is done. Sorry for missing these things.

    Here's the init:

    SCB->SCR |= SCB_SCR_SEVONPEND_Msk; 
    NRF_RNG->INTENSET = RNG_INTENSET_VALRDY_Msk; 
    NRF_RNG->TASKS_START   = 1; 
    

    And in your main loop:

    *snip*
    while (NRF_RNG->EVENTS_VALRDY == 0)
    {
      __WFE();
    }
    NRF_RNG->EVENTS_VALRDY = 0;
    NVIC_ClearPendingIRQ(RNG_IRQn);
    // Read out data from NRF_RNG->VALUE
    *snip*
    

    Note that if you're using the second revision of nRF51822 (FA/GC/G0) then all known issues related to the RNG is fixed.

Reply
  • I setup a small project to test this, and you'll need to init a couple of things, as well as clear pending IRQ after the event is done. Sorry for missing these things.

    Here's the init:

    SCB->SCR |= SCB_SCR_SEVONPEND_Msk; 
    NRF_RNG->INTENSET = RNG_INTENSET_VALRDY_Msk; 
    NRF_RNG->TASKS_START   = 1; 
    

    And in your main loop:

    *snip*
    while (NRF_RNG->EVENTS_VALRDY == 0)
    {
      __WFE();
    }
    NRF_RNG->EVENTS_VALRDY = 0;
    NVIC_ClearPendingIRQ(RNG_IRQn);
    // Read out data from NRF_RNG->VALUE
    *snip*
    

    Note that if you're using the second revision of nRF51822 (FA/GC/G0) then all known issues related to the RNG is fixed.

Children
  • That's very clever and thanks for doing the work on this. So I can see what you're doing there is making the VALRDY event generate an interrupt using INTENSET but not enabling the interrupt. Then the SEVONPEND causes the pended interrupt to generate an event.

    So from that I'll take it that my hypothesis that peripheral events like VALDRY are not directly 'events' as far as the Cortext is concerned, ie they won't wake from __WFE() directly, is correct. You've very cleverly found a way to make that happen. That actually makes sense now I think about it more, there are loads of peripherals in the system, if every event caused the system to wake up, it would never get to sleep!

Related