RTOS(Real-Time Operating System), 트 플래그 그룹 생성, 대기(Pend) 방식, 비트 제어


RTOS(Real-Time Operating System)를 공부하는 분들이라면 이벤트 플래그를 통해 태스크 간 동기화를 어떻게 처리하는지 잘 이해하셔야 합니다. 본 포스팅에서는 이벤트 플래그 그룹 생성, 대기(Pend) 방식, 비트 제어(포스트) 방식에 대해 순차적으로 살펴보겠습니다.

목차

  1. 이벤트 플래그(Event Flag)란?
  2. 이벤트 플래그 그룹과 자료구조
  3. 이벤트 플래그 그룹 생성: OSFlagCreate()
  4. 이벤트 플래그 대기: OSFlagPend()
  5. 이벤트 플래그 설정/해제: OSFlagPost()
  6. 마무리 및 참고

1. 이벤트 플래그(Event Flag)란?

이벤트 플래그는 여러 태스크(Task)가 특정 조건(비트 패턴)이 만족될 때까지 대기하거나, 만족되었을 때 이를 알려주는 역할을 하는 동기화 기법입니다.

  • 비트의 ON/OFF 여부에 따라 태스크들이 원하는 ‘이벤트 발생(비트 ON)’ 혹은 ‘이벤트 소멸(비트 OFF)’을 기다릴 수 있습니다.
  • uC/OS-II에서는 이벤트 플래그를 8/16/32비트로 관리할 수 있습니다. (컴파일 옵션 및 RTOS 설정에 따라 달라짐)

이벤트 플래그는 태스크 간 자원 공유, 센서 데이터 준비 완료 신호, 타이머나 인터럽트 처리가 끝났음을 알리는 등 다양한 상황에서 사용됩니다.


2. 이벤트 플래그 그룹과 자료구조

uC/OS-II에서는 이벤트 플래그를 ‘그룹(Group)’ 단위로 관리합니다. 각 그룹은 다음과 같은 정보를 포함합니다.

c

복사편집

typedef struct {

    INT8U     OSFlagType;      // 이 구조가 이벤트 플래그임을 표시

    void     *OSFlagWaitList;  // 이 플래그를 기다리는 태스크들에 대한 대기 리스트

    OS_FLAGS  OSFlagFlags;     // 이벤트 플래그(비트) 상태

} OS_FLAG_GRP;

  • OSFlagWaitList는 이 이벤트 플래그 그룹을 기다리고 있는 태스크들의 연결 리스트를 가리킵니다.
  • OSFlagFlags는 각 이벤트의 ON/OFF(비트 1/0) 상태를 나타냅니다.

또한, 태스크가 이벤트 플래그를 기다릴 때 생기는 구조체인 OS_FLAG_NODE도 존재합니다.

c

복사편집

typedef struct {

    void     *OSFlagNodeNext;   

    void     *OSFlagNodePrev;

    void     *OSFlagNodeTCB;       // 플래그를 기다리는 태스크의 TCB

    void     *OSFlagNodeFlagGrp;   // 어느 이벤트 플래그 그룹을 기다리는지

    OS_FLAGS  OSFlagNodeFlags;     // 기다리는 비트 패턴(예: 0xD1)

    INT8U     OSFlagNodeWaitType;  // AND 또는 OR 조건 등

} OS_FLAG_NODE;

  • OSFlagNodeFlags: 태스크가 대기하는 비트 패턴 저장
  • OSFlagNodeWaitType: AND 대기(모든 비트가 1이어야), OR 대기(한 비트만 1이어도) 등 대기 유형 표시

요약

  • OS_FLAG_GRP: 이벤트 플래그의 그룹 상태 및 대기 리스트 정보
  • OS_FLAG_NODE: 각 태스크가 기다리는 비트와 대기 조건을 관리

3. 이벤트 플래그 그룹 생성: OSFlagCreate()

이벤트 플래그 그룹을 생성하려면 OSFlagCreate() 함수를 사용합니다.

c

복사편집

OS_EVENT *OSFlagCreate (OS_FLAGS flags, INT8U *err)

{

    OS_FLAG_GRP *pgrp;

    OS_ENTER_CRITICAL();

    pgrp = OSFlagFreeList;               // 사용 가능한 OS_FLAG_GRP 구조체 가져오기

    if (pgrp != (OS_FLAG_GRP *)0) {

        OSFlagFreeList = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList;

        pgrp->OSFlagType     = OS_EVENT_TYPE_FLAG;  // 이벤트 타입 설정

        pgrp->OSFlagFlags    = flags;               // 초기 플래그(비트) 설정

        pgrp->OSFlagWaitList = (void *)0;           // 대기 리스트 초기화(아직 대기 태스크 없음)

        OS_EXIT_CRITICAL();

        *err = OS_NO_ERR;               // 에러 없음

    } else {

        // 생성 불가 시 처리

        OS_EXIT_CRITICAL();

        *err = OS_ERR_FLAG_CREATE;

        return (OS_EVENT *)0;

    }

    return (pgrp);

}

  • flags: 이벤트 플래그 그룹을 생성할 때 초기값으로 설정할 비트 패턴
  • OS_MAX_FLAGS: uC/OS-II 설정 파일(OS_CFG.H)에서 최대 생성 가능한 이벤트 플래그 그룹 수를 정의

해당 함수를 호출하면 새로운 이벤트 플래그 그룹이 만들어져, 이후 비트 조작이나 대기를 할 수 있게 됩니다.


4. 이벤트 플래그 대기: OSFlagPend()

4.1 사용 목적

OSFlagPend() 함수는 특정 플래그(비트)가 만족될 때까지 태스크를 대기 상태로 전환시키는 역할을 합니다. 예를 들어,

  • 모든 비트가 ON(1)이 되어야 태스크를 깨운다 (AND 조건)
  • 비트 중 하나라도 ON(1)이면 태스크를 깨운다 (OR 조건)
  • 반대로 OFF(0)를 기다릴 수도 있음

4.2 함수 원형

c

복사편집

OS_FLAG_GRP *OSFlagPend (

    OS_FLAG_GRP *pgrp,

    OS_FLAGS     flags,

    INT8U        wait_type,

    INT16U       timeout,

    INT8U       *err

)

  • pgrp: 대기할 이벤트 플래그 그룹
  • flags: 대기할 비트 패턴(예: 0x0F)
  • wait_type: AND 대기(모든 비트), OR 대기(아무 비트 하나) 등
  • timeout: 시간 초과(타임아웃) 설정. 만약 그 시간이 지나도 조건이 만족 안 되면 에러 반환
  • *err: 에러 상태를 반환받기 위한 변수

4.3 동작 방식 개요

  1. 이벤트 플래그 그룹의 현재 상태(pgrp->OSFlagFlags)와 flags를 비교
  2. 조건이 이미 만족한다면(비트가 이미 ON 또는 OFF) 즉시 반환
  3. 조건 불만족 시, 태스크를 대기 상태로 만들고 OSFlagWaitList에 연결(이 과정에서 OS_FLAG_NODE 생성)
  4. 다른 태스크나 인터럽트에서 해당 비트가 만족되는 순간, OSFlagPost()를 통해 깨어남
  5. 지정한 타임아웃 내에 조건이 만족되지 않으면 에러 코드(OS_TIMEOUT) 반환

예시: AND 대기(모든 비트가 켜질 때까지 대기)

c

복사편집

case OS_FLAG_WAIT_SET_ALL:

    flags_rdy = pgrp->OSFlagFlags & flags;

    if (flags_rdy == flags) {

        // 이미 조건 만족 -> 플래그 수정, 태스크 즉시 진행

        pgrp->OSFlagFlags &= ~flags_rdy;

    } else {

        // 불만족 -> 대기 상태로 전환

        // OS_FlagBlock() 내부에서 대기 리스트에 추가

    }


5. 이벤트 플래그 설정/해제: OSFlagPost()

5.1 함수 설명

다른 태스크나 인터럽트 서비스 루틴(ISR)에서 특정 이벤트가 발생했음을 알리려면, 이벤트 플래그를 ON(1)으로 설정하거나 때로는 OFF(0)으로 바꿔주어야 합니다.
OSFlagPost() 함수를 이용하면 이벤트 플래그 그룹 내 비트를 ‘설정(SET)’ 혹은 ‘해제(CLEAR)’ 할 수 있습니다.

5.2 함수 원형

c

복사편집

OS_EVENT *OSFlagPost (

    OS_FLAG_GRP *pgrp,

    OS_FLAGS     flags,

    INT8U        opt,

    INT8U       *err

)

  • pgrp: 수정할 이벤트 플래그 그룹
  • flags: 켜거나 끌(ON/OFF) 비트 패턴
  • opt: 설정(SET)인지 해제(CLEAR)인지, AND/OR 대기 해제 조건 등
  • *err: 에러 상태 반환

5.3 코드 예시

c

복사편집

switch (opt) {

    case OS_FLAG_CLR:

        // 특정 비트 OFF

        pgrp->OSFlagFlags &= ~flags;

        break;

    case OS_FLAG_SET:

        // 특정 비트 ON

        pgrp->OSFlagFlags |= flags;

        break;

    // 필요에 따라 WAIT_SET_ALL, WAIT_SET_ANY 등 분기

}

비트가 업데이트된 이후, 이 플래그를 기다리던 태스크들의 대기 조건이 충족되면 Ready(준비 상태)로 전환됩니다. 이후 스케줄러에 의해 해당 태스크가 CPU를 점유할 수 있게 됩니다.


6. 마무리 및 참고

6.1 핵심 요약

  1. OS_FLAG_GRP: 이벤트 플래그 그룹의 핵심 구조체
  2. OSFlagCreate(): 이벤트 플래그 그룹 생성
  3. OSFlagPend(): 원하는 비트 패턴 만족 시까지 태스크를 대기
  4. OSFlagPost(): 이벤트 플래그 비트 ON/OFF로 다른 태스크 깨우기

이벤트 플래그는 태스크 간 동기화에 매우 유용합니다. 특히, 여러 개의 자원을 기다리거나 여러 신호 중 하나만 오면 바로 처리해야 하는 경우(OR 대기), 모든 신호가 완료될 때까지 기다리는 경우(AND 대기) 등 다양한 시나리오에 적용할 수 있습니다.

6.2 참고 사항

  • OS_MAX_FLAGS 설정: 프로젝트에서 사용할 이벤트 플래그 그룹 개수가 충분히 커야 합니다.
  • 이벤트 플래그는 세마포어나 큐, 메일박스와 함께 uC/OS-II의 대표적인 IPC(Inter-Process Communication) 기법 중 하나입니다.
  • 실제 코드 구현 시 타임아웃, 인터럽트 우선순위 등을 고려해야 합니다.

  • uC/OS-II 이벤트 플래그, Real-Time OS, RTOS 이벤트 플래그, Event Flag Group, OSFlagCreate, OSFlagPend, OSFlagPost, 플래그 동기화, 태스크 동기화, 임베디드 RTOS

이상으로 uC/OS-II 이벤트 플래그(Event Flag) 관리에 대한 전반적인 내용을 살펴보았습니다. RTOS 설계나 임베디드 시스템에서 태스크 간 동기화가 필요한 상황이라면, 이벤트 플래그를 어떻게 설정하고 대기(펜딩)하며, 언제 포스트하는지 숙지해두면 많은 도움이 될 것입니다.

글이 도움되셨다면, 공감(좋아요)과 댓글 부탁드립니다!
궁금한 점이 있으면 언제든 댓글로 남겨주세요. 감사합니다.


참고 링크

  • uC/OS-II 공식 문서
  • 임베디드 RTOS 실습 자료

Leave a Comment