cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WLE immediately exist Stop2 when using UTILS_ENTER_CRITICAL_SECTION()

Strooom
Associate III

I am doing a LoRaWAN project on the STM32WLE and so I want to power it down in Stop2 mode to lower the power consumption.

Using the following code, this works fine :

            UTILS_ENTER_CRITICAL_SECTION();                                                // mask interrupts
            if (applicationEventBuffer.isEmpty() && loraWanEventBuffer.isEmpty()) {        // If no events are pending in any of the eventBuffers...
                HAL_SuspendTick();                                                         // stop Systick
                HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);                               // go into Sleep - STOP2
                HAL_ResumeTick();                                                          // re-enable Systick
            }                                                                              //
            UTILS_EXIT_CRITICAL_SECTION();                                                 // re-enable interrupts

However, when some of my other code uses UTILS_ENTER_CRITICAL_SECTION(); to make things thread safe between the main thread and the interrupt-handlers, the device does not stay into Stop2 but wakes up immediately..

Commenting out the UTILS_ENTER_CRITICAL_SECTION();  UTILS_EXIT_CRITICAL_SECTION(); it works as it should, but then the code is not thread safe anymore... 

Here's what those macro's are doing (utilities_conf.h)

#define UTILS_ENTER_CRITICAL_SECTION() uint32_t primask_bit= __get_PRIMASK();\
  __disable_irq()
 
#define UTILS_EXIT_CRITICAL_SECTION()  __set_PRIMASK(primask_bit)

Any hints on how to solve this in a clean way ?

Thank you!

1 ACCEPTED SOLUTION

Accepted Solutions
Strooom
Associate III

Ok, this has been solved.

The reason was that some return path of the function did not re-enable the interrupts (my mistake), and apparently when they are disabled, the WFI does not stop the MCU, which makes sense.

View solution in original post

5 REPLIES 5
Strooom
Associate III

Some more experimenting shows that

__get_PRIMASK();

and

__enable_irq();

are NOT causing the problem, but

__disable_irq();

is.

when some of the other code in the main loop, executes __disable_irq(); then later, the MCU will not stay into stop2 anymore

Strooom
Associate III

Ok, this has been solved.

The reason was that some return path of the function did not re-enable the interrupts (my mistake), and apparently when they are disabled, the WFI does not stop the MCU, which makes sense.

Piranha
Chief II

Disabling interrupts globally doesn't stop the CPU from entering sleep modes, but it also doesn't stop the CPU from waking up on a pending interrupt. It is designed like that on purpose. Look at my post in this topic for a practical example.

ST's examples for Stop modes are broken. A correct approach is described in this topic. Also take a note that the wireless MCUs have some additional specifics. And read this article for a deeper understanding of low-power modes and wake-up features. Plus this topic, if RTC wake-up is involved.

Strooom
Associate III

Thank you @Piranha​, this is all useful info. Indeed my wakeup is based on RTC.

The reason the MCU did not go into sleep in my case was that interrupts were disabled (by mistake) and at least one was pending. So the pending one didn't get serviced (and cleared) and it also prevented the MCU from going into sleep.

I'll take a look at all the content you referred to and come back with more info if usefull.

Have a nice weekend!

Hello

Thanks for your solution. Can you elaborate more on how you solved the problem?