Это четко задокументированы , что , когда глобальные данные совместно с ISR и основной программой, то данные должны быть объявлены volatile
для того , чтобы видимость гарантии памяти (и , что достаточно только для данных 1 байт, требуется какой- либо большое специальные меры , чтобы гарантировать также атомарность) , Здесь у нас есть хорошие правила:
- Переменные, используемые только вне ISR, не должны быть изменчивыми.
- Переменные, используемые только внутри ISR, не должны быть изменчивыми.
- Переменные, используемые как внутри, так и вне ISR, должны быть изменчивыми.
Но volatile
необходимо, когда к переменной обращаются из> 1 ISR, но не совместно используют вне ISR? Например, у меня есть функция, которая поддерживает внутреннее состояние, используя static
переменную:
void func() {
static volatile long counter; // volatile or not?
// Do stuff with counter etc.
}
Эта функция вызывается двумя способами: из прерывания вывода и из библиотеки TimerOne :
attachInterrupt(0, func, CHANGE);
Timer1.attachInterrupt(func);
Нет проблем атомарности, поскольку при вводе ISR прерывания автоматически отключаются , но это volatile
больше вопрос компилятора: что кэшируется, а что нет.
Лучше в безопасности, чем потом сожалеть, конечно ...
volatile
, поскольку она не модифицируется ничем, кроме генерируемого кода; Компилятор может «предполагать», что ISR выполняется линейно, и так и есть, пока прерывания не вкладываются. В этом есть смысл. Спасибо!