I have noticed that the description in the SDCC manual for the __critical
keyword is inaccurate for the STM8 platform.
As of version 4.2.0, the manual says in section 3.9.1 (emphasis mine):
A special keyword may be associated with a block or a function declaring it as __critical. SDCC will generate code to disable all interrupts upon entry to a critical function and restore the interrupt enable to the previous state before returning.
This is wrong given the current implementation of __critical
for STM8. On this platform, __critical
is essentially a wrapper of sim
and rim
instructions around the critical function's or block's code. The rim
instruction, however, simply sets the CC register I1/I0 flags to fixed values of 1/0, for interrupt priority level zero (lowest level). It does not restore the I1/I0 flags to whatever previous state (i.e. different priority level) they may have been in.
The current implementation of __critical
for STM8 means it is useless to use inside an ISR in the scenario where you are using nested interrupts (i.e. have assigned different priorities to certain interrupts with the ITC_SPRx registers) and one wants to block execution of other higher-priority interrupts inside that ISR. The current documentation of __critical
could mislead one to assume that this application would work.
It looks like this issue is not limited to stm8: for targets, where there is no efficient way to restore the old state, interrupts are simply enabled on the end of the __critial section. Looks like we explicitly need to document behaviour for all targets.
Fixed in [r13771].
Related
Commit: [r13771]