Skip to main content
rcummings
Associate
August 11, 2010
Question

WFI Race Condition

Posted on August 11, 2010 at 17:37

WFI Race Condition

    This topic has been closed for replies.

    9 replies

    John F.
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    Hi,

    Disable interrupts before preparing to sleep? Re-enable them on wake-up?

    rcummings
    rcummingsAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    I thought about that as a possibility, but won't disabling interrupts prevent the WFI from waking the chip back up?

    RonCK

    John F.
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    Yes. It's going to depend on the mode you enter and how you can arrange to exit it.

    Please see section 4.3 in the RM0008 Reference manual Rev 11. For example, consider using WFE as described below.

    Exiting Sleep mode

    If the WFI instruction is used to enter Sleep mode, any peripheral interrupt acknowledged by

    the nested vectored interrupt controller (NVIC) can wake up the device from Sleep mode.

    If the WFE instruction is used to enter Sleep mode, the MCU exits Sleep mode as soon as

    an event occurs. The wakeup event can be generated either by:

    �? enabling an interrupt in the peripheral control register but not in the NVIC, and enabling

    the SEVONPEND bit in the Cortex-M3 System Control register. When the MCU

    resumes from WFE, the peripheral interrupt pending bit and the peripheral NVIC IRQ

    channel pending bit (in the NVIC interrupt clear pending register) have to be cleared.

    �? or configuring an external or internal EXTI line in event mode. When the CPU resumes

    from WFE, it is not necessary to clear the peripheral interrupt pending bit or the NVIC

    IRQ channel pending bit as the pending bit corresponding to the event line is not set.

    This mode offers the lowest wakeup time as no time is wasted in interrupt entry/exit.

    rcummings
    rcummingsAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    So you got me thinking about the possibility of playing with interrupt enabling/disabling.  I tried this:

    void WaitForCycleTime(void)

    {

       while(stBaseTimer.bCycleTimeFlag == FALSE)

       {

          __enable_interrupt();

          __WFI();

          __disable_interrupt();

       }

       __enable_interrupt();

    }

    This should disable interrupts just during the evaluation of the while loop.  This reduced the occurrence rate but did not eliminate it.  On the scope there is 16us from the falling edge of the EXTI interrupt to the rising edge of the SysTick interrupt.  That's 64 processor clocks.  How is it taking that long to roll over?  John, I will think about the WFE possibilities.

    regards,

    RonCK

    rcummings
    rcummingsAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    OK,  I fixed it, though if anyone has a better idea how to do this, please let me know.

    void WaitForCycleTime(void)

    {

       while(stBaseTimer.bCycleTimeFlag == FALSE)

       {

          if((SysTick->VAL > 500) && (SysTick->VAL < (CLOCKS_PER_CYCLE-500)))

          {

             __WFI();

          }

       }

    }

    The if statement inside the while prevents it from going to sleep within a 250us window around the occurrence of SysTick.  This window ensures that the flag that gets set in the SysTick interrupt has time to be updated.

    regards,

    RonCK

    rcummings
    rcummingsAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    In this app the EXTI interrupts are measuring the frequency of two external lines.  Those frequencies are critical to the app, so I can't disable them.  I can't effectively ignore them during a window either.

    regards,

    RonCK

    domen23
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    Why can't you just disable EXTI?

    rcummings
    rcummingsAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    Joseph, Stuart, and John, 

       I was able to get this WFE swap working this morning.  It seems to be a fine answer, and is decidedly more elegant than what I had forced on Wednesday evening.

    Best regards,

    Ron

    joseph239955_st
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 14:01

    Hi Ron,

    Please use WFE instead of WFI for this idle loop.

    void WaitForCycleTime(void)

    {

        while(stBaseTimer.bCycleTimeFlag == FALSE)

       {

           __WFE();

        }

    }

    And put __SEV(); in your SysTick handler.

    If a event is detected (generated by SEV) then the WFE will not enter sleep.

    Hope this helps.

    Joseph