void main(void) { uiCommonTimer = 1000; PORTA = 10; PORTB = 5; { unsigned int uitemp; // __disable_interrupt(); uitemp = uiCommonTimer; // __enable_interrupt(); eeTestTime = 1000 - uitemp; }
Результат:
315 { 316 unsigned int uitemp; 317 // __disable_interrupt(); 318 uitemp = uiCommonTimer; 319 // __enable_interrupt(); 320 eeTestTime = 1000 - uitemp;
\ 00000010 EE08 LDI R16, 232 \ 00000012 E013 LDI R17, 3 \ 00000014 1904 SUB R16, R4 \ 00000016 0915 SBC R17, R5 \ 00000018 E141 LDI R20, 17 \ 0000001A .... RCALL __eeput16_8
321 }
Пестня! В R17:R16 грузится тыща, и прямо из них вычитаются R5:R4. Ничего лишнего, оптимум на 100%.
Теперь добавляем "атомарности" чтения регистрового счетчика. Просто запрещаем на время прерывания. И теперь получаем вот что:
315 { 316 unsigned int uitemp; 317 __disable_interrupt();
\ 00000010 94F8 CLI
318 uitemp = uiCommonTimer;
\ 00000012 0192 MOVW R19:R18, R5:R4
319 __enable_interrupt();
\ 00000014 9478 SEI
320 eeTestTime = 1000 - uitemp;
\ 00000016 E000 LDI R16, 0 \ 00000018 2711 CLR R17 \ 0000001A E141 LDI R20, 17 \ 0000001C .... RCALL __eeput16_8
321 }
Здравствуй жопа новый год. Что не так-то?
Если счётчик организовать не в регистрах, а в ОЗУ, тогда компилятор не приходит в эррегированное состояние. Когда ОЗУ, тогда ему всё равно, запрещены прерывания, или нет:
315 { 316 unsigned int uitemp; 317 __disable_interrupt();
\ 00000012 94F8 CLI
318 uitemp = uiCommonTimer;
\ 00000014 8120 LD R18, Z \ 00000016 8131 LDD R19, Z+1
319 __enable_interrupt();
\ 00000018 9478 SEI
320 eeTestTime = 1000 - uitemp;
\ 0000001A EE08 LDI R16, 232 \ 0000001C 1B02 SUB R16, R18 \ 0000001E 0B13 SBC R17, R19 \ 00000020 E141 LDI R20, 17 \ 00000022 .... RCALL __eeput16_8
321 }
Похоже, действительно, есть какая-то недокуметнированная несовместимость между __regvar и volatile. А простой запрет прерываний каким тут боком? Вот это вобще не понятно... Очень жаль. Работа напрямую с регистрами гораздо быстрее. Ладно, предупреждён, значит вооружён. Может, кому-то эта информация будет полезна. :))