Ожидание флага из прерывания зависает в релизной сборке
uint8_t data_ready = 0;
void USART1_IRQHandler(void) {
/* ... чтение регистра данных ... */
data_ready = 1;
}
void wait_data(void) {
while (data_ready == 0) { }
data_ready = 0;
}
С флагом -O0 прошивка работает. После сборки с -O2 устройство зависает в wait_data, хотя логическим анализатором видно, что прерывание приходит и обработчик выполняется.
Что произошло?
- Переменная не объявлена volatile: оптимизатор считает, что в цикле она не меняется, и держит её в регистре
- Прерывание не успевает выставить флаг до проверки: в цикл ожидания нужно добавить небольшую задержку
- Проблема в типе uint8_t: обращение к одному байту на 32-битном ядре неатомарно, флаг читается наполовину
- Нужно запретить прерывания на время цикла ожидания, иначе выставленный флаг теряется при следующем прерывании
