volatile — это квалификатор языка Си, который говорит, что переменная может изменятся в другом потоке (обработчике прерываний) или является указателем на регистр. Иначе говоря, volatile отключает оптимизацию обращения к этой переменной.
В качестве примера рассмотрим программу для микроконтроллеров avr atmega.
Объявляем переменную cnt;
unsigned char cnt; |
Допустим, у нас есть прерывание от таймера, которое срабатывает каждую миллисекунду.
ISR( TIMER0_OVF_vect ) { if( cnt != 0 ) { cnt--; } } |
А вот часть основного цикла программы, в которой мы хотим сделать задержку 100 мс.
cnt = 100; //выставляем сколько ждать while( cnt != 0 ); //ждем |
Кажется, все должно работать.
Но если посмотреть дизасемблированный код, то будет понятно, что из цикла ожидания мы никогда не выйдем.
ldi r25, 0x64 ; загружаем 100 в регистр r25 sts 0x0100, r25 ; копируем значение из регистра r25 в переменную cnt loop: rjmp loop ; мёртвый цикл |
Компилятор в результате оптимизации убрал проверку значения переменной сnt и создал мертвый цикл.
Но если переменную cnt опишем как:
volatile unsigned char cnt; |
все волшебным образом заработает.
Посмотрим опять в ассемблерный код
ldi r25, 0x64 ; загружаем 100 в регистр r25 sts 0x0100, r25 ; копируем значение из регистра r25 в переменную cnt loop: lds r24, 0x0100 ;загружаем в регистр r24 значение переменной cnt and r24,r24 ;проверяем на ноль значение регистра r24 brne loop ;если в регистре не 0, то повторяем проверку |
Теперь в цикле есть проверка значения переменной.
Скажите пожалуйста, через что вы дизассемблируете. Можете поподробнее рассказать куда заходить нужно :)
Написал заметку http://mainloop.ru/avr-atmega/avr-disassembler.html, надеюсь, поможет.
Очень интересная статья на тему: http://we.easyelectronics.ru/Soft/skolzkaya-dorozhka-dlya-poklonnikov-volatile.html
«Скользкая дорожка для поклонников volatile»