Está claramente documentado que, quando os dados globais são compartilhados com um ISR e o programa principal, os dados precisam ser declarados volatile
para garantir a visibilidade da memória (e isso basta apenas para dados de 1 byte; qualquer coisa maior precisa de disposições especiais para garantir também a atomicidade) . Aqui temos boas regras:
- Variáveis usadas apenas fora de um ISR não devem ser voláteis.
- Variáveis usadas apenas dentro de um ISR não devem ser voláteis.
- As variáveis usadas dentro e fora de um ISR devem ser voláteis.
Mas é volatile
necessário quando a variável é acessada em> 1 ISRs, mas não compartilhada fora dos ISRs? Por exemplo, eu tenho uma função que mantém o estado interno usando uma static
variável:
void func() {
static volatile long counter; // volatile or not?
// Do stuff with counter etc.
}
Essa função é chamada de duas maneiras: de interrupção de pinos e da biblioteca TimerOne :
attachInterrupt(0, func, CHANGE);
Timer1.attachInterrupt(func);
Não há problemas de atomicidade, pois quando um ISR é inserido, as interrupções são desativadas automaticamente , mas essa volatile
é mais uma pergunta do compilador: o que é armazenado em cache e o que não é.
Melhor prevenir do que remediar, é claro ...
volatile
, pois não é modificada por nada além do código que está sendo gerado; O compilador pode "assumir" que o ISR é executado linearmente e o faz, desde que as interrupções não sejam aninhadas. Isso faz sentido. Obrigado!