This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How do you put the nrf51822 chip to sleep?

I am wondering how you put the nrf51822 chip to sleep. I've determined that the way to do this with the soft device is sd_app_event_wait() in the while loop. What about non-softdevice?

I am wanting to have it sleep until woken by interrupts, then sleep again. In another example, I found __wfi() used. Also, __WFI(). Neither seem to do anything, though.

Thanks!

Parents
  • Calling __WFE twice is basically the same as doing a __WFI.

    When waiting for something in a loop it's usually best to use __WFE(). This is to avoid hitting race conditions if you are waiting for a flag for instance.

    In the code below, we are waiting for a timer compare event to trigger. If you want to save power while waiting, then you should use a __WFE() instruction.

    
    main()
    {
      ...
    
      while(flag == 0)
      {
        __WFE();  
      }
    
      ...
    }
    
    TIMER_ISR()
    {
      flag = true;
    }
    
    

    __WFE has an internal event flag that will prevent it from going to sleep if it's set. In addition, if you call it and the event flag is set, __WFE will clear it. The event flag is set by a number of different things in the CPU including returning from an interrupt.

    In the case above, the TIMER interrupt is enabled and will set a flag. Whenever there is a wake-up event in the system, the loop will check if the timer event has happened or else it will sleep.

    If you use __WFI() in the case above, there is a race condition. __WFI will sleep if you call it and wake up if there is a wake-up event. But it does not have an internal event register that prevents it from sleeping if something has occured. This means that if the timer interrupt occurs after you checking for (flag == 0) but before calling __WFI(), you could end up sleeping forever.

    There's also more differences between WFI/WFE that are shown in the table below: https://devzone.nordicsemi.com/index.php/discussions?controller=attachment&task=displayFile&tmpl=component&id=195

    SEVONPEND and PRIMASK are internal processor registers that can be configured. In short, SEVONPEND enables you to wake up to interrupts occuring at a lower priority then the current context in which __WFE is called. __WFI does not care about the SEVONPEND status. It's only __WFI that can wake up when PRIMASK (aka. __disable_interrupts()) is set.

    WFE_WFI_wake_ups.jpg

Reply
  • Calling __WFE twice is basically the same as doing a __WFI.

    When waiting for something in a loop it's usually best to use __WFE(). This is to avoid hitting race conditions if you are waiting for a flag for instance.

    In the code below, we are waiting for a timer compare event to trigger. If you want to save power while waiting, then you should use a __WFE() instruction.

    
    main()
    {
      ...
    
      while(flag == 0)
      {
        __WFE();  
      }
    
      ...
    }
    
    TIMER_ISR()
    {
      flag = true;
    }
    
    

    __WFE has an internal event flag that will prevent it from going to sleep if it's set. In addition, if you call it and the event flag is set, __WFE will clear it. The event flag is set by a number of different things in the CPU including returning from an interrupt.

    In the case above, the TIMER interrupt is enabled and will set a flag. Whenever there is a wake-up event in the system, the loop will check if the timer event has happened or else it will sleep.

    If you use __WFI() in the case above, there is a race condition. __WFI will sleep if you call it and wake up if there is a wake-up event. But it does not have an internal event register that prevents it from sleeping if something has occured. This means that if the timer interrupt occurs after you checking for (flag == 0) but before calling __WFI(), you could end up sleeping forever.

    There's also more differences between WFI/WFE that are shown in the table below: https://devzone.nordicsemi.com/index.php/discussions?controller=attachment&task=displayFile&tmpl=component&id=195

    SEVONPEND and PRIMASK are internal processor registers that can be configured. In short, SEVONPEND enables you to wake up to interrupts occuring at a lower priority then the current context in which __WFE is called. __WFI does not care about the SEVONPEND status. It's only __WFI that can wake up when PRIMASK (aka. __disable_interrupts()) is set.

    WFE_WFI_wake_ups.jpg

Children
No Data
Related