Це чітко задокументовані , що , коли глобальні дані спільно з 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 виконується лінійно, і це робиться, доки переривання не гніздяться. Що має сенс. Дякую!