C++11/17 facilities to use the interrupt capabilities of AVR. It can be thought as a C++ version to the C headers avr/interrupt.h and util/atomic.h from AVR Libc.(Why?)
#include <avr/interrupt.hpp>
using namespace avr::interrupt;
int main() {
on(); //enable global interrupts
off(); //disable global interrupts
{ //scope with code executed without being disturbed by interrupts
atomic s;
//code
} //interrupts are enabled at the end if they were enabled before
{
atomic s{on_at_the_end};
//code
} //interrupts are always enabled at the end
{ //scope with code executed with interrupts enabled
interruptible s;
//code
} //interrupts are disabled at the end if they were disabled before
{
interruptible s{off_at_the_end};
//code
} //interrupts are always disabled at the end
}
The demo above uses C++17 but C++11 can also be used, take a look at demo/atomic.cpp or demo/interruptible.cpp to see how.
Note, simplifications are taken into account in order to achieve a more expressive documentation, please, open avr/interrupt.hpp to see the real prototypes or declarations.
Enable global interrupts.
Disable global interrupts.
RAII to execute code without being disturbed by interrupts. By default the state of the status register is recovered at the end of the scope, which means that global interrupts are enabled again only if they were enabled before. If the argument on_at_the_end
is passed to the constructor then global interrupts are always enabled at the end of the scope.
Note, the compiler optimizer can reorder the code around the atomic scope that doesn’t have any observable side effect. Take a look at reordering_code.org if timing is a critical factor.
RAII to execute code with interrupts enabled. By default the state of the status register is recovered at the end of the scope, which means that global interrupts are disabled again only if they were disabled before. If the argument off_at_the_end
is passed to the constructor then global interrupts are always disabled at the end of the scope.
Note, the compiler optimizer can reorder the code around the atomic scope that doesn’t have any observable side effect. Take a look at reordering_code.org if timing is a critical factor.
It communicates to the compiler that the lvalue v
has an observable side effect. Take a look at reordering_code.org.
Macro to define ISR(Interrupt Service Routine) routines. The parameter vector
is the name of the interrupt vector and the variable argument can be used to put additional attributes.
For each interrupt there is a short macro using the form AVRINT_<name_of_the_interrupt>(...)
. The <name_of_the_interrupt>
is the one defined by the datasheet and sometimes there is a more extensive version with a more expressive name, for example, considering an ATtiny13A
there is the macro AVRINT_TIM0_OVF(...)
but there is also the alias AVRINT_TIMER_OVERFLOW(...)
.
- Add the
include
directory to your include path and the include patch to avrIO(if you want to use it instead ofavr/io.h
). - Add
#include <avr/interrupt.hpp>
to your source and enjoy it!
void f() {
avr::interrupt::on();
avr::interrupt::off();
avr::interrupt::atomic s;
//code
}
/*
00000000 <_Z1fv>:
0: 78 94 sei
2: f8 94 cli
4: 8f b7 in r24, 0x3f ; 63
6: f8 94 cli
8: 8f bf out 0x3f, r24 ; 63
a: 08 95 ret
*/
-std=c++17 -Os -mmcu=attiny13a
void f() {
sei();
cli();
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
//code
}
}
/*
00000000 <_Z1fv>:
0: 78 94 sei
2: f8 94 cli
4: 8f b7 in r24, 0x3f ; 63
6: f8 94 cli
8: 8f bf out 0x3f, r24 ; 63
a: 08 95 ret
*/
}
-std=c++17 -Os -mmcu=attiny13a
avr-gcc
with at least-std=c++11
.- avrIO or
avr/io.h
from AVR Libc.
Contributions are welcome, if you like what you see and you have interest to help, don’t hesitate to open a PR(pull request), a issue or contact me through my email.