Вступить в клуб →
средняявопросМикроконтроллеры и аппаратные протоколы

Ожидание флага из прерывания зависает в релизной сборке

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-битном ядре неатомарно, флаг читается наполовину
  • Нужно запретить прерывания на время цикла ожидания, иначе выставленный флаг теряется при следующем прерывании

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела