The C Standard mandates that a signal handler may access only objects of type sig_atomic_t (besides lock-free atomics). Accesses to objects of other types produce UB. An interrupt service routine resembles a signal handler, so this restriction must be obeyed when writing ISRs.
avr-libc's signal.h is broken in that it does not declare type sig_atomic_t, though it does declare a variable of that name, of type volatile signed char. Presumably, that was meant to be a typedef.
But if you want an ISR to access, say, a systick counter of type uint32_t then that would produce UB.
Are there any special precautions / exceptions from the standard that avr-gcc imposes, so that it would be possible to write a strictly conforming ISR?
As you tagged the question
avr-gcc, I'll assume GCC1 in the remainder. It's not possible to do it in a performing way due to 2 reasons:There is no way to write an ISR in a conforming way. avr-gcc uses attributes to implement this.
avr-gcc implements neither atomic types nor atomic builtins (where the latter are compiler specific of course, so you can ignore them for conforming discussion). Even if avr-gcc implemented atomic types, using libatomic would be considered inappropriate due to its resource consumption by most AVR folks. And even the simple atomic accesses that could be performed by the compiler without resorting to lib code are not implemented. Take for example:
All three functions will forward to
__atomic_load_2, which does not exists (as of avr-gcc v13), and respective insns don't exist, either. Or more precisely: there are generic versions in libatomic, but bachend avr has libatomic disabled.So the closest you can do is to use these primitives to implement atomic magic, and also to provide these functions. By its very nature, these functions cannot be inlined. So the only reasonable approach is to implement this in the compiler backend itself, which is somewhere in
./gcc/config/avr/avr.md2,3.1 Hence
avr-gccoravr-g++and AVR-LibC. Dunno how the situation is for other compiler brands like IAR.2 You can use the vanilla non-atomic loads and stores code emitters, but you'll have to get an 8-bit tmp reg
Rxso you canfor the simple cases.
__tmp_reg__can't be used here for obvious reasons.3 I just got ranted for globally switching off IRQs. So if you want to avoid that, you'll have to go the libatomic way and allocate semaphores. No need so say that this is extremely expensive compared to the usual approaches.