Ответ 1
Объявите переменную как volatile
:
volatile unsigned global;
Это ключевое слово, которое сообщает компилятору, что global
может быть изменен в разных потоках, и все оптимизации должны быть отключены для него.
Рассмотрим следующий фрагмент кода:
unsigned global;
while(global);
global
изменяется в функции, вызываемой IRQ. Однако g++ удаляет тест "is-not-zero" и переводит цикл while в бесконечный цикл.
Отключение оптимизации компилятора решает проблему, но предлагает ли С++ для него конструкцию языка?
Объявите переменную как volatile
:
volatile unsigned global;
Это ключевое слово, которое сообщает компилятору, что global
может быть изменен в разных потоках, и все оптимизации должны быть отключены для него.
Поскольку вы используете GCC, и вы говорите, что создание переменной volatile
не работает, вы можете обмануть оптимизатора, считая, что цикл изменяет переменную, лежа в компиляторе:
while(global)
asm volatile("" : "+g"(global));
Это инструкция встроенной сборки, в которой говорится, что она изменяет переменную (она передается в качестве операнда ввода-вывода). Но он пуст, поэтому, очевидно, он ничего не делает во время выполнения. Тем не менее, оптимизатор считает, что он изменяет переменную - программисты сказали так, а компилятор, запрещающий замену операнда (что означает просто замену одного текста другим), на самом деле не волнует тело встроенной сборки и не будет делать никаких забавные вещи к нему.
И поскольку тело пустое, а ограничение использует его наиболее общее, оно должно надежно работать на всех платформах, где GCC поддерживает встроенную сборку.
Вы можете использовать атрибуты GCC в объявлении функции для отключения оптимизации на основе каждой функции:
void myfunc() __attribute__((optimize(0)));
Для получения дополнительной информации см. страницу GCC Function Attributes.