그라운드 임베디드 유튜브 구독

노트 / RTOS

펌웨어RTOS4 / 8

세마포어와 뮤텍스: 공유 자원 지키기

두 태스크가 같은 UART나 변수를 동시에 건드리면 데이터가 섞입니다. 뮤텍스로 잠그고, 세마포어로 신호를 줍니다.

GROUND EMBEDDED · 정리 노트RTOS 04세마포어와 뮤텍스 1xSemaphoreTake(uart_mutex, portMAX_DELA… 2uart_send(buf, len); 3xSemaphoreGive(uart_mutex);

문제

태스크 A가 UART로 "TEMP=25"를 보내는 도중 태스크 B가 끼어들어 "SPD=100"을 보내면 "TEMSPD=100P=25"가 나갑니다. 공유 자원은 한 번에 하나만 쓰게 해야 합니다.

뮤텍스: 열쇠 하나

xSemaphoreTake(uart_mutex, portMAX_DELAY);
uart_send(buf, len);
xSemaphoreGive(uart_mutex);
  • 가진 태스크만 돌려줄 수 있습니다.
  • 우선순위 상속이 들어 있어 우선순위 역전을 줄입니다.
  • 인터럽트에서는 쓰지 않습니다.

세마포어: 신호

  • 이진 세마포어: "일이 생겼다"는 신호. 인터럽트가 Give, 태스크가 Take하며 기다림
  • 카운팅 세마포어: 자원이 N개일 때(버퍼 슬롯 N개) 남은 개수 관리
void USART1_IRQHandler(void) {        // 인터럽트
    BaseType_t woken = pdFALSE;
    xSemaphoreGiveFromISR(rx_sem, &woken);
    portYIELD_FROM_ISR(woken);
}

인터럽트에서는 반드시 FromISR 버전 함수를 씁니다.

데드락

A가 자원1을 잡고 자원2를 기다리고, B가 자원2를 잡고 자원1을 기다리면 둘 다 영원히 멈춥니다. 여러 자원을 잡을 때는 항상 같은 순서로 잡고, 잡고 있는 시간을 짧게 합니다. 아예 자원을 하나의 태스크가 소유하고 다른 태스크는 큐로 요청하게 만드는 것이 더 안전한 설계입니다.