Ключевое слово volatile – это спецификатор, применяемый при объявлении переменной. Он сообщает компилятору, что значение переменной может изменяться в любой момент – без какого-либо действия со стороны кода, который компилятор обнаруживает поблизости.
Переменная должна быть объявлена с ключевым словом volatile всякий раз, когда ее значение может измениться неожиданно. На практике так ведут себя только три типа переменных:
1. Отображаемые в памяти периферийные регистры
2. Глобальные переменные, изменяемые в обработчике прерывания
3. Глобальные переменные, используемые в многопотоковом приложении
2. Глобальные переменные, изменяемые в обработчике прерывания
3. Глобальные переменные, используемые в многопотоковом приложении
Встраиваемые системы содержат оборудование со сложной периферией. В составе периферии есть регистры, чьи значения могут изменяться асинхронно алгоритму программы. В качестве простого примера рассмотрим 8-битный регистр состояния, отображаемый в памяти по адресу 0х1234. Допустим, нам нужно опрашивать регистр состояния до тех пор, пока он не станет ненулевым. Простая и неправильная реализация может быть такой:
uint8_t * pReg = (uint8_t *) 0x1234;
// Wait for register to become non-zero
while (*pReg == 0) { } // Do something else
В этом случае, почти наверняка будет сбой, как только вы включите оптимизацию. Компилятор сгенерирует ассемблерный код подобный этому:
mov ptr, #0x1234
mov a, @ptr
loop:
bz loop
Логическое обоснование оптимизатора довольно простое: уже считав значение переменной в аккумулятор (вторую строка кода), нет необходимости считывать его заново, поскольку значение всегда будет тем же. Таким образом, в третьей строке мы окажемся в бесконечном цикле. Чтобы заставить компилятор сделать то, что нам нужно, мы изменим описание на:
uint8_t volatile * pReg = (uint8_t volatile *) 0x1234;
Ассемблерный код теперь выглядит следующим образом:
mov ptr, #0x1234
loop:
mov a, @ptr
bz loop
Заблуждаетесь, читайте http://we.easyelectronics.ru/blog/Soft/2593.html
ОтветитьУдалить