쓰기 1로 지우는 상태 레지스터에 |=를 쓰면 이름 붙인 비트보다 더 많이 지워진다.
#include <stdint.h>
#define UART_SR (*(volatile uint32_t *)0x40004000u)
#define SR_ORE (1u << 3) /* overrun, write 1 to clear */
void clear_overrun_wrong(void) { UART_SR |= SR_ORE; }
void clear_overrun(void) { UART_SR = SR_ORE; }
오버런 플래그는 1을 써야 지워진다. 0을 쓰면 아무 일도 없다. UART_SR |= SR_ORE는 먼저 레지스터 전체를 읽는다. 그 순간 걸려 있던 쓰기 1 지우기 플래그는 전부 1로 읽히고 그대로 1로 다시 쓰이니 전부 지워진다. 처리기가 아직 보지 않은 프레이밍 오류도 함께 사라진다.
Cortex-M에서 -O2로 보면 틀린 쪽은 ldr, orr, str이다. 맞는 쪽은 마스크를 한 번 str하는 것이 전부다. volatile은 두 접근을 프로그램에 남긴다. 다시 써 넣은 비트를 하드웨어가 어떻게 다루는지는 말해 주지 않는다.