But why are you using different priorities at all?
Without a concrete reason why interrupt A has to have higher priority than interrupt B, the only sane thing to do is have them be the same priority.
Maybe I'm not using different priorities today, maybe I will later, and maybe there will be a good reason, or maybe the reason will not be good. I simply protect something needing protection so whether priorities get changed or not, it needs no additional thought later. I can apply this same 'rule' consistently to all isr's with anything that needs protection. Maybe there are only a few of these around, or maybe there are quite a few, it doesn't matter as they all get the same treatment.
If protection is not needed due to it being the highest priority or all irq's are the same priority, the cost of the unneeded protection is simply an extra 3 instructions. If a higher priority irq is blocked for the time protection is active, and it had no need of the var being protected, then that irq was delayed for a dozen cpu cycles unnecessarily. If a higher priority irq is blocked for the time protection is active, and it DID have a need to use the protected var then that protection was necessary and useful. A minimal cost to never have to deal with it again. The code, such as for a systick timer, can move over to any number of cortex mcu's and it will never be subject to the decisions being made about irq priorities. There will be no notes in the code that will specify it needs to be highest priority, because it simply doesn't matter. Instead of checking your code for these problems you may have left for yourself if/when changing priorities, you can instead just focus on whether your priority change was useful or not.
example- are these interrupt locks necessary? maybe not in someIsr() and maybe not in time() as I have not said what priority someIsr() is using nor did I specify from where time() may be called. But why pre-determine at what priority time() can be safely called and who will be calling it, and also why pre-determine what irq priority someIsr() will be in relation to all the others? The protection is simple and of such little cost, it seems to me it will be worth doing so you never have to revisit this particular potential problem ever again. You figured out a var could need interrupt protection for both the write and read and took care of it. It will always be correct from day 1, and a future me cannot screw it up later.
static volatile u64 ms;
void someIsr(){
InterruptLock lock;
ms++;
}
u64 time(){
InterruptLock lock;
return ms;
}
These class interrupt protections can also be put in a scope, which you would do in a larger function to keep the protection only where its needed. The class constructor saves the irq state at the point of object definition, the destructor restores irq state at the end of scope.
Another example would be something like stm32 gpio registers. Some of them are shared among pins on the same port. If you want to turn on a pin pullup, or reconfigure a pin, or set it to analog, or whatever else that will modify these shared registers- do you want to pre-determine in what run level you can safely do those things? do you restrict all code that touches these registers to the same run level? do you want to restrict all pin config to a single point in time? why not simply interrupt protect any modifications to these registers so one no longer has to worry about whether some isr is changing a pin while some lower run level was also changing a pin on the same port. You no longer have a restriction about where you can reconfigure a pin- it can be done anywhere and you no longer have a potential problem. Whether you setup all pins in a single place once, or let any code setup or modify a pin, it will always work correctly and there will be no possibility one of these register modifications will be interrupted where another run level may be wanting to modify the same register. I think this is also worth doing simply because it eliminates a potential problem that never has to dealt with or thought about ever again, also with very little cost.
I have looked around to see who also interrupt protects these gpio registers, and found that NuttX does, not sure about Zephyr as I cannot read what they are doing, and I doubt any ST HAL code is doing so. If NuttX is doing the same, at least is suggests my thinking is correct.
I'm not interrupt protecting everything in sight, nor am I declaring everything volatile. The protection is done when it is needed or may be needed as previously stated, the volatile is done when needed, after some thought and after checking the compiler output (and in -Os so no false assurances). I think I am acting sanely, but if not at least whatever I'm doing is working out well for me.