Ну вообщем, проверил на железе - не приводит к установке флага прерывания от компаратора дрыг режимом фронт/спад. Плохо, конечно. Пришлось перенести на прерывание от EEPROM и завести флаг запроса. Теперь это выглядит примерно так
Код
#define TASK2_LOCK GPIOR0_Bit0
#define TASK3_LOCK GPIOR0_Bit1
#define TASK2_WAKEUP GPIOR0_Bit2
#define DISABLE_TASK2() {EECR_EERIE=0;}
#define ENABLE_TASK2() {EECR_EERIE=1;}
#define WAKEUP_TASK2() {TASK2_WAKEUP=1;}
#pragma diag_suppress=Ta006
__interrupt void TASK2(void)
{
__no_operation();
//....
//....много всякой долгой каки...
main(); //Например так
//....
__no_operation();
}
#pragma diag_default=Ta006
#pragma vector=EE_RDY_vect
__interrupt __raw void TASK2dispatch(void)
{
DISABLE_TASK2();
TASK2_LOCK=1;
TASK2_WAKEUP=0;
__enable_interrupt();
((void(*)(void))TASK2)();
__disable_interrupt();
TASK2_LOCK=0;
if (TASK2_WAKEUP) ENABLE_TASK2();
}
#pragma diag_suppress=Ta006
__interrupt void TASK3(void)
{
__no_operation();
//....
//....не очень много всякой долгой каки...
if (PINB_Bit0) WAKEUP_TASK2(); //К примеру
//....
__no_operation();
}
#pragma diag_default=Ta006
#pragma vector=TIMER0_OVF_vect
__interrupt __raw void TASK3dispatch(void)
{
if (TASK3_LOCK) return;
TASK3_LOCK=1;
DISABLE_TASK2();
__enable_interrupt();
((void(*)(void))TASK3)();
__disable_interrupt();
TASK3_LOCK=0;
if (TASK2_LOCK) return;
if (TASK2_WAKEUP) ENABLE_TASK2();
}
#pragma vector=INT0_vect
__interrupt void TASK4(void)
{
//Тут тоже колдовство, запрещаем все прерывания, например
TIMSK0=0;
//Запрещаем и TASK2
DISABLE_TASK2();
__enable_interrupt();
//Чего-то делаем, тут еще бывает INT1, но это уже не суть
__disable_interrupt();
if (PINB_Bit1) WAKEUP_TASK2(); //К примеру
TIMSK0=1<<TOV0;
if (TASK3_LOCK) return;
if (TASK2_LOCK) return;
if (TASK2_WAKEUP) ENABLE_TASK2();
}
И код
Код
RSEG CODE:CODE:NOROOT(1)
// 48 __interrupt void TASK2(void)
TASK2:
// 49 {
ST -Y, R24
ST -Y, R31
ST -Y, R30
ST -Y, R3
ST -Y, R2
ST -Y, R1
ST -Y, R0
ST -Y, R23
ST -Y, R22
ST -Y, R21
ST -Y, R20
ST -Y, R19
ST -Y, R18
ST -Y, R17
ST -Y, R16
IN R24, 0x3F
// 50 __no_operation();
NOP
// 51 //....
// 52 //....много всякой долгой каки...
// 53 main(); //Например так
RCALL main
// 54 //....
// 55 __no_operation();
NOP
// 56 }
OUT 0x3F, R24
LD R16, Y+
LD R17, Y+
LD R18, Y+
LD R19, Y+
LD R20, Y+
LD R21, Y+
LD R22, Y+
LD R23, Y+
LD R0, Y+
LD R1, Y+
LD R2, Y+
LD R3, Y+
LD R30, Y+
LD R31, Y+
LD R24, Y+
RETI
// 57 #pragma diag_default=Ta006
// 58
// 59
// 60 #pragma vector=EE_RDY_vect
RSEG CODE:CODE:NOROOT(1)
// 61 __interrupt __raw void TASK2dispatch(void)
TASK2dispatch:
// 62 {
// 63 DISABLE_TASK2();
CBI 0x1F, 0x03
// 64 TASK2_LOCK=1;
SBI 0x1E, 0x00
// 65 TASK2_WAKEUP=0;
CBI 0x1E, 0x02
// 66 __enable_interrupt();
SEI
// 67 ((void(*)(void))TASK2)();
RCALL TASK2
// 68 __disable_interrupt();
CLI
// 69 TASK2_LOCK=0;
CBI 0x1E, 0x00
// 70 if (TASK2_WAKEUP) ENABLE_TASK2();
SBIC 0x1E, 0x02
SBI 0x1F, 0x03
// 71 }
??TASK2dispatch_0:
RETI
REQUIRE _A_EECR
REQUIRE _A_GPIOR0
// 72
// 73 #pragma diag_suppress=Ta006
RSEG CODE:CODE:NOROOT(1)
// 74 __interrupt void TASK3(void)
TASK3:
// 75 {
// 76 __no_operation();
NOP
// 77 //....
// 78 //....не очень много всякой долгой каки...
// 79 if (PINB_Bit0) WAKEUP_TASK2(); //К примеру
SBIC 0x03, 0x00
SBI 0x1E, 0x02
// 80 //....
// 81 __no_operation();
??TASK3_0:
NOP
// 82 }
RETI
REQUIRE _A_GPIOR0
REQUIRE _A_PINB
// 83 #pragma diag_default=Ta006
// 84
// 85 #pragma vector=TIMER0_OVF_vect
RSEG CODE:CODE:NOROOT(1)
// 86 __interrupt __raw void TASK3dispatch(void)
TASK3dispatch:
// 87 {
// 88 if (TASK3_LOCK) return;
SBIC 0x1E, 0x01
RJMP ??TASK3dispatch_0
// 89 TASK3_LOCK=1;
SBI 0x1E, 0x01
// 90 DISABLE_TASK2();
CBI 0x1F, 0x03
// 91 __enable_interrupt();
SEI
// 92 ((void(*)(void))TASK3)();
RCALL TASK3
// 93 __disable_interrupt();
CLI
// 94 TASK3_LOCK=0;
CBI 0x1E, 0x01
// 95 if (TASK2_LOCK) return;
SBIC 0x1E, 0x00
RJMP ??TASK3dispatch_0
// 96 if (TASK2_WAKEUP) ENABLE_TASK2();
SBIC 0x1E, 0x02
SBI 0x1F, 0x03
??TASK3dispatch_0:
RETI
REQUIRE _A_EECR
REQUIRE _A_GPIOR0
// 97 }
// 98
// 99 #pragma vector=INT0_vect
RSEG CODE:CODE:NOROOT(1)
// 100 __interrupt void TASK4(void)
TASK4:
// 101 {
ST -Y, R17
ST -Y, R16
IN R17, 0x3F
// 102 //Тут тоже колдовство, запрещаем все прерывания, например
// 103 TIMSK0=0;
LDI R16, 0
STS 110, R16
// 104 //Запрещаем и TASK2
// 105 DISABLE_TASK2();
CBI 0x1F, 0x03
// 106 __enable_interrupt();
SEI
// 107 //Чего-то делаем, тут еще бывает INT1, но это уже не суть
// 108 __disable_interrupt();
CLI
// 109 if (PINB_Bit1) WAKEUP_TASK2(); //К примеру
SBIC 0x03, 0x01
SBI 0x1E, 0x02
// 110 TIMSK0=1<<TOV0;
??TASK4_0:
LDI R16, 1
STS 110, R16
// 111 if (TASK3_LOCK) return;
SBIC 0x1E, 0x01
RJMP ??TASK4_1
// 112 if (TASK2_LOCK) return;
SBIC 0x1E, 0x00
RJMP ??TASK4_1
// 113 if (TASK2_WAKEUP) ENABLE_TASK2();
SBIC 0x1E, 0x02
SBI 0x1F, 0x03
??TASK4_1:
OUT 0x3F, R17
LD R16, Y+
LD R17, Y+
RETI
В принципе, из-за того, что управление прерыванием доступно через SBI/CBI время нахождения в состоянии с запрещенным прерыванием даже уменьшилось... Красота только пропала