CMSIS-RTOS Keil RTX - Proper way to enter ARM deep-sleep
<p>Hello I would like to know what is the proper way to put ARM Cortex M0+ to deep sleep. Particularly I'm using CMSIS-RTOS RTX.</p>

<p>The way my IRQ is handled is that ISR just set OS Signal and clear IRQ. Eg.:</p>

<pre><code>void ISR_A(){
  osSignalSet(ID_Task_Handling_IRQ_A, IRQ_A_SIGNAL_CODE);
  DisableIRQ_A();
}
</code></pre>

<p>Then in my idle loop</p>

<pre><code>void os_idle_demon(void) {
...
timeToSleep = os_suspend(); // get from OS how long I can sleep and also stop OS scheduling
LPTMR_Init(timeToSleep,...) // set wakeup timer
POWER_EnterLLS(void)        // enter deep sleep. Set registers and calls WFI instruction
// after wakup compute actual slpetTime
os_resume(sleptTime); // enable OS scheduling
}
</code></pre>

<p>The problem is that my ISR does not handles IRQ fully (it just set signal in OS and some thread will handle it according to priority and scheduling - I would like to keep it this way). But when IRQ comes in between <code>os_suspend()</code> and <code>__wfi()</code> instruction then IRQ is cleared but task can not be scheduled (because <code>os_suspend()</code>). When CPU get to WFI it goes to sleep and thus OS thread that shall handle signal from ISR never executes. But CPU is also not woken up by (pad) IRQ because that is already handled.  </p>

<p>The question is how to atomically do the check that there is no task pending and start WFI.</p>

<p>Something like</p>

<pre><code>if( ! OS_Signal_Is_rised) {  
  // only do it atomically because what if IRQ would come here?
  wfi; 
}
</code></pre>