asteroid7 писал(а):Не увидел в этом коде ошибки... Не затруднит Вас разъяснить этот момент.
Единственное, что бросается в глаза, это логическое "==" без скобок. Так это допускается стандартом.
А её и компилятор не видит

Я ж говорю, он не догадывается ни о чём.
Тут
может быть логическая ошибка,
в точности та же, что и в Вашем примере про 8-битный контроллер и 16-битные данные.
Если переменные
a и
b меняются в прерывании
вместе и должны обрабатываться
согласованно (я привёл сравнение просто в качестве примера примитивной обработки), то их надо читать обязательно в общей критической секции в две временные переменные и только потом обрабатывать. Но компилятор об этом не знает, поэтому и не предупреждает. В отличие от прямого сравнения
a == b, где он ворчит о возможной зависимости от порядка чтения.
Кстати, не всегда даже 16-битную переменную (имеются ввиду 8-битники, конечно), изменяемую в прерывании, обязательно читать в крит. секции. Пусть у нас есть таймаут, декрементируемый в прерывании до 0.
Код: Выделить всё
volatile uint16_t timeout;
some_ISR()
{
if( timeout ) --timeout;
}
bool is_timeout_expired()
{
return HIGH_BYTE( timeout ) == 0 && LOW_BYTE( timeout ) == 0;
}
Тут немного условно показано. И ISR без привязки к компилятору, и не показано само чтение. Можно timeout сделать объединением { uint16_t u; uint8_t b[2]; } и в макросах читать из байтовой части, можно в макросах обращаться по приведённому к (volatile uint8_t *) указателю со смещениями, не важно.
Важно то, что прерывание только декрементирует переменную и 0 уже не трогает.
С (и
С++ для встроенного оператора
&&) гарантирует, что вычисление операндов идёт слева направо с прекращением вычислений, когда результат уже ясен. Поэтому чтение сначала старшей части безопасно.
Старшая часть если уже стала 0, то при анализе младшей уже не поменяется.
А если ещё не 0, то младшая и не зачитывается.
Если за время сравнения с 0 старшей части младшая меняется — ну и ладно. Если к тому времени сама станет нулём — тем лучше, раньше узнаем об окончании таймаута

Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.