I did not fully understand the dont_sleep
thing, but one thing you could try is do the "main work" in the PendSV handler, set to the lowest priority. Then just schedule a PendSV from other handlers each time you need something done. See here how to do it (it's for M1 but M3 is not too different).
Another thing you could use (maybe together with the previous approach) is the Sleep-on-exit feature. If you enable it, the processor will go to sleep after exiting the last ISR handler, without you having to call WFI. See some examples here.
The Cortex M3 supports a useful pair of operations of operations (common in many other machines as well) called "Load-Exclusive" (LDREX) and "Store-Exclusive" (STREX). Conceptually, the LDREX operation performs a load, also sets some special hardware to observe whether the location that got loaded might be written by something else. Performing a STREX to the address used by the last LDREX will cause that address to be written only if nothing else wrote it first. The STREX instruction will load a register with 0 if the store took place, or 1 if it was aborted.
Note that STREX is often pessimistic. There are a variety of situations where it might decide not to perform the store even if the location in question had not in fact been touched. For example, an interrupt between an LDREX and STREX will cause the STREX to assume the location being watched might have been hit. For this reason, it's usually a good idea to minimize the amount of code between the LDREX and STREX. For example, consider something like the following:
inline void safe_increment(uint32_t *addr)
{
uint32_t new_value;
do
{
new_value = __ldrex(addr) + 1;
} while(__strex(new_value, addr));
}
which compiles to something like:
; Assume R0 holds the address in question; r1 trashed
lp:
ldrex r1,[r0]
add r1,r1,#1
strex r1,r1,[r0]
cmp r1,#0 ; Test if non-zero
bne lp
.. code continues
The vast majority of the time the code executes, nothing will happen between the LDREX and STREX to "disturb" them, so the STREX will succeed without further ado. If, however, an interrupt happens to occur immediately following the LDREX or ADD instruction, the STREX will not perform the store, but instead the code will go back to read the (possibly updated) value of [r0] and compute a new incremented value based upon that.
Using LDREX/STREX to form operations like safe_increment makes it possible to not only manage critical sectionsm, but also in many cases to avoid the need for them.
Best Answer
The core ARM architecture supports two different types of interrupts - pulse sensitive and level sensitive. (See ARMv6-M Architecture Reference Manual, Section B3.4.1) In either case, if two interrupts happen at the same, or one of them happens while the first interrupt is being processed, the second interrupt will be processed when the first interrupt service routine returns and re-enables interrupts.
The source of a level-sensitive interrupt will stay active until the interrupt service routine clears it. If the interrupt service routine does not clear the interrupt source, a second interrupt will be generated as soon as interrupts are re-enabled. The source can be cleared by reading a data register for instance, or in some cases by explicitly clearing a flag.
The pulse sensitive interrupt will set a flag that will generate the interrupt, however the pulse needs to be long enough for the processor to catch it. If the pulse is not long enough, it will not be caught. The interrupt service routine needs to explicitly clear the flag.
I am not sure what will happen in the case where two level sensitive interrupts happen at the same time and the interrupt service routine does something with the peripheral that will acknowledges both interrupts. An example of this would be a USART driver that was handling both Rx and Tx interrupts. I believe that the second interrupt will not be seen since it is no longer active when interrupt are re-enabled. I am right in the middle of an ARM project and unless someone posts the answer, I will do some testing and edit this answer with the results.