Необходима ли изменчивость, когда переменная доступна из> 1 ISR, но не используется совместно с ISR?

9

Это четко задокументированы , что , когда глобальные данные совместно с 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 :

  1. attachInterrupt(0, func, CHANGE);
  2. Timer1.attachInterrupt(func);

Нет проблем атомарности, поскольку при вводе ISR прерывания автоматически отключаются , но это volatileбольше вопрос компилятора: что кэшируется, а что нет.

Лучше в безопасности, чем потом сожалеть, конечно ...

Joonas Pulakka
источник

Ответы:

9

volatile только информирует генератор кода компилятора о том, что переменная может быть изменена чем-то иным, чем генерируемый код, поэтому нельзя предполагать, что ее копия остается точной.

Код ISR должен быть написан / сгенерирован в предположении, что он не имеет контекста при входе, и должен сохранять контекст ЦП вокруг его собственной операции (ISR). Таким образом, как и в случае с неделимостью неатомарных операций, волатильность зависит, в данном случае * , от того, разрешено ли прерывание вкладывать или нет. Если не вложенность гарантирована, совместно используемая переменная не может быть изменена кем-либо кроме этого ISR во время ее собственного выполнения. Если ваш ISR когда-нибудь может быть использован в среде, где прерывания могут быть вложены, то это ограничение больше не будет выполняться.

* в данном случае :
я предполагаю, что здесь поддерживается переменная, поддерживаемая программным обеспечением. Если мы говорим о переменной, которая может быть обновлена ​​аппаратным событием, например, регистром таймера, все ставки выключены: переменная является изменчивой, несмотря ни на что.

JRobert
источник
Итак, до тех пор, пока я не изменю стандартное поведение Arduino «прерывания не вкладывают», переменная не должна быть volatile, поскольку она не модифицируется ничем, кроме генерируемого кода; Компилятор может «предполагать», что ISR выполняется линейно, и так и есть, пока прерывания не вкладываются. В этом есть смысл. Спасибо!
Joonas Pulakka