#include "avr/io.h"
#include "avr/interrupt.h"
/* Самое что ни на есть стандартное С-шное средство - нелокальные переходы
* ANSI C89 - 4.6 NON-LOCAL JUMPS setjmp.h
* C99 - 7.13 Nonlocal jumps setjmp.h
*/
#include "setjmp.h"
/* это так, для удобства */
#define ATOMIC_CODE(_statements_4_atomic_execution_) \
do { \
uint8_t _atomic_saved_sreg_ = SREG; \
cli(); \
{ _statements_4_atomic_execution_ } \
SREG = _atomic_saved_sreg_; \
} while(0)
/* буфер состояния процессора */
jmp_buf my_super_puper_main_point;
uint8_t isr_super_job_1()
{
// bla_bla;
return 1;
}
uint8_t isr_super_job_2()
{
// bla_bla_bla;
return 2;
}
#define isr_super_job_default isr_super_job_1
uint8_t (* volatile isr_super_job)(void) = isr_super_job_default;
void main_work(void)
{
/* часть 1 */
ATOMIC_CODE( isr_super_job = isr_super_job_1; );
// шо-то делаем, вызываем какие-то функции - не важно, где произойдёт прерывание
/* часть 2 */
ATOMIC_CODE( isr_super_job = isr_super_job_2; );
// аналогично
}
int main()
{
// настроили прерывания и прочие bla_bla_bla;
sei();
for(;;) {
// bla_bla_bla_bla;
switch( setjmp( my_super_puper_main_point) ) {
case 0: // ещё никто никуда не уходил
main_work();
break;
case 1: // "вернулись" из прерывания, прерывание произошло в чаcти программы "1"
// bla_bla_bla;
break;
case 2: // "вернулись" из прерывания, прерывание произошло в чаcти программы "2"
// bla_bla_bla;
break;
}
}
}
ISR(ANA_COMP_vect)
{
// вызываем нужный обработчик и возвращаем в точку switch( setjump ...
// как "статус" то, что вернул обработчик
longjmp( my_super_puper_main_point, isr_super_job() );
}