임베디드에서 인터럽트와 메인이 같은 레지스터·변수를 만질 때 반드시 걸리는 문제다.
사라지는 수정
메인: REG 읽기 (0x00)
← 여기서 인터럽트 발생, ISR 이 REG 에 0x02 를 씀
메인: 0x01 로 고쳐 쓰기 → 0x01
ISR 이 쓴 0x02 가 사라졌다
해법 셋
/* ① 짧은 임계 구역 */
__disable_irq();
REG |= (1u << 5);
__enable_irq(); // 가능한 짧게. 길면 인터럽트 지연이 늘어난다
/* ② 하드웨어가 제공하는 단일 명령 쓰기 */
GPIOA->BSRR = (1u << 5); // set/reset 전용 레지스터 — 읽지 않으므로 안전
/* ③ 비트밴딩 */
변수에도 같은 문제가 있다
32비트 MCU 에서 uint32_t 대입은 보통 단일 명령이지만, 64비트 값이나 구조체는 아니다.
volatile 은 최적화만 막을 뿐 원자성을 주지 않는다 — 이 둘을 섞어 이해하는 것이 흔한 오해다.