Чи потрібна мінливість при доступі до змінної з> 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більше питання компілятора: що кешується, а що ні.

Безпечніше, ніж шкода, звичайно ...

Відповіді:


9

volatile тільки інформує генератор коду компілятора, що змінна може бути змінена чимось іншим, ніж генерується код, щоб не припускати, що будь-яка її копія залишається точною.

Код ISR повинен бути записаний / згенерований з припущенням, що він не має контексту при введенні, і зберігати контекст процесора навколо його власної роботи (ISR). Отже, як і при неподільності неатомних операцій, в цьому випадку мінливість залежить від того, дозволено чи ні переривання до гніздування. Якщо гарантовано вкладення, загальна змінна не може змінюватися іншою, ніж ця ISR, під час її власного виконання. Якщо ваш ISR коли-небудь може бути використаний в середовищі, де переривання дозволено гніздо, то це обмеження більше не буде в силі.

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


Отже, доки я не змінюю поведінку за замовчуванням Arduino "перебиває не гніздо", змінна не повинна бути volatile, оскільки вона не модифікується нічим іншим, ніж генерується код; компілятор може "припустити", що ISR виконується лінійно, і це робиться, доки переривання не гніздяться. Що має сенс. Дякую!
Joonas Pulakka
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.