임베디드 용어 사전
GPIO·인터럽트

링 버퍼

고정 크기 배열을 원형으로 쓰는 큐. ISR이 넣고 메인이 꺼내는 임베디드의 표준 구조다.

circular buffer. 생산자와 소비자의 속도 차이를 흡수한다.

static volatile uint8_t buf[64];
static volatile uint8_t head, tail;      /* 크기를 2의 거듭제곱으로 두면 & 로 감쌀 수 있다 */

void ring_put(uint8_t c) {               /* ISR 에서 호출 */
    uint8_t next = (head + 1u) & 63u;
    if (next != tail) { buf[head] = c; head = next; }   /* 가득 차면 버린다 */
}

int ring_get(void) {                     /* 메인에서 호출 */
    if (head == tail) return -1;
    uint8_t c = buf[tail];
    tail = (tail + 1u) & 63u;
    return c;
}

왜 락이 필요 없나

생산자는 head 만, 소비자는 tail 만 쓴다. 각각 자기 인덱스만 갱신하므로 단일 생산자·단일 소비자 구조에서는 인터럽트를 끄지 않아도 안전하다. 인덱스 갱신이 원자적이어야 하므로 인덱스 타입을 CPU 워드보다 크게 잡지 않는다.

넘칠 때의 정책을 정해 둔다

버린다        최신 데이터가 중요할 때
덮어쓴다      로그처럼 최근 이력만 남기면 될 때
플래그를 세운다  놓쳤다는 사실 자체를 알려야 할 때  ← 대부분 이게 필요하다

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 인터럽트와 NVIC — 하던 일을 멈추고 달려가기