메일박스는 이전 기사에서 Nucleus SE에서 시그널 다음으로 가장 직관적인 태스크 간 통신 메커니즘으로 소개되었습니다. 태스크 간 단순 데이터 전송을 위한 저비용, 고유연성 방법을 제공합니다.
메일박스 사용하기
Nucleus SE에서 메일박스는 빌드 타임에 정의됩니다. 애플리케이션당 최대 16개 메일박스를 구성할 수 있습니다. 0개로 구성하면 컴파일러가 관련 데이터 구조와 API 코드를 모두 생략해 바이너리를 가볍게 유지합니다.
메일박스는 본질적으로 ADDR 타입의 단일 변수를 담을 수 있는 저장 슬롯입니다. 한 번에 한 태스크만 메일박스에 쓸 수 있습니다. 꽉 차면 읽거나 리셋될 때까지 후속 쓰기 시도는 실패합니다. API 옵션에 따라 꽉 찬 메일박스에 쓰기 시도는 에러를 반환하거나 공간이 생길 때까지 태스크를 일시 중단할 수 있습니다.
메일박스 vs 큐
일부 OS는 메일박스를 단일 엔트리 큐로 대체합니다. 큐가 메일박스 동작을 흉내 낼 수 있지만, 헤드/테일 포인터, 더 큰 데이터 구조, 더 많은 코드 경로 등 추가 오버헤드가 있어 메모리 사용량과 실행 시간이 증가합니다.
Nucleus SE에서는 메일박스 또는 큐 중 선택할 수 있습니다. 설계가 많은 큐와 적은 메일박스를 사용한다면, 메일박스를 큐로 교체하면 데이터 크기가 약간 늘지만 메일박스 전용 API 코드가 제거되어 유지보수가 단순해집니다. 두 구성을 모두 테스트해 메모리 풋프린트와 성능을 비교하기 쉽습니다.
큐는 향후 기사에서 다룰 예정입니다.
메일박스 구성
메일박스 개수
nuse_config.h의 핵심 매크로는 NUSE_MAILBOX_NUMBER입니다. 기본값은 0으로 메일박스가 비활성화됨을 의미합니다. 1에서 16 사이의 정수로 설정할 수 있습니다. nuse_config_check.h의 컴파일 타임 체크가 범위 초과 시 에러를 발생시킵니다.
0이 아닌 값으로 설정하면 메일박스 서브시스템이 활성화되어 데이터 구조가 크기 조정되고 API 활성화 심볼이 처리됩니다.
API 활성화
각 메일박스 API 호출은 nuse_config.h에 해당하는 #define을 가집니다:
NUSE_MAILBOX_SEND
NUSE_MAILBOX_RECEIVE
NUSE_MAILBOX_RESET
NUSE_MAILBOX_INFORMATION
NUSE_MAILBOX_COUNT
기본적으로 모두 FALSE로 설정되어 호출과 구현이 비활성화됩니다. API를 사용하려면 해당 매크로를 TRUE로 설정하세요. 메일박스가 구성되지 않은 상태에서 API를 활성화하면 컴파일 타임 에러가 발생합니다(NUSE_Mailbox_Count()는 항상 사용 가능). 비활성화된 API를 호출하면 링크 타임 에러가 발생합니다.
/* 시스템 내 메일박스 수 – 0-16 */ #define NUSE_MAILBOX_NUMBER 0 /* 서비스 콜 인에이블러: */ #define NUSE_MAILBOX_SEND FALSE #define NUSE_MAILBOX_RECEIVE FALSE #define NUSE_MAILBOX_RESET FALSE #define NUSE_MAILBOX_INFORMATION FALSE #define NUSE_MAILBOX_COUNT FALSE
메일박스 서비스 콜
Nucleus SE는 9가지 메일박스 관련 서비스 콜을 제공합니다. SE에 구현된 것들은:
NUSE_Mailbox_Send() – 메일박스에 메시지 쓰기.
NUSE_Mailbox_Receive() – 메일박스에서 메시지 읽기.
NUSE_Mailbox_Reset() – 태스크 일시 중단 없이 메일박스 클리어.
NUSE_Mailbox_Information() – 메일박스 상태 쿼리.
NUSE_Mailbox_Count() – 구성된 메일박스 수 반환.
생성, 삭제, 대량 검색, 브로드캐스트 같은 다른 기능은 SE에 구현되지 않았습니다.
쓰기 및 읽기 연산
메일박스는 보내기(쓰기)와 받기(읽기) 두 가지 핵심 연산을 지원합니다. 두 API 모두 Nucleus RTOS와 Nucleus SE에서 사용 가능하며, 유연성과 에러 처리에서 일부 차이가 있습니다.
메일박스로 보내기
Nucleus RTOS에서 NU_Send_To_Mailbox 콜은 메일박스가 꽉 찼을 때 무기한 또는 시간 제한 일시 중단을 지원합니다. Nucleus SE는 단순화된 버전을 제공합니다: 일시 중단은 선택 사항이며 타임아웃은 지원하지 않습니다.
Nucleus SE 샘플 프로토타입:
STATUS NUSE_Mailbox_Send(NUSE_MAILBOX mailbox, ADDR *message, U8 suspend);
블로킹이 비활성화되면 루틴은 메일박스 상태 플래그를 확인합니다. 비어 있으면 데이터를 쓰고 메일박스를 꽉 찬 것으로 표시; 그렇지 않으면 NUSE_MAILBOX_FULL을 반환합니다.
블로킹이 활성화되면 메시지가 성공적으로 게시되거나 수신 연산에 의해 태스크가 깨어날 때까지 루프를 돕니다. 태스크가 메일박스에서 일시 중단된 경우, 성공적인 전송 후 즉시 재개됩니다.
다음 발췌는 블로킹이 활성화된 경우의 핵심 로직을 보여줍니다(가독성을 위해 단순화):
do { if (!NUSE_Mailbox_Status[mailbox]) { // 메일박스 비어 있음 – 데이터 저장 및 대기 중인 태스크 깨우기 } else if (suspend == NUSE_NO_SUSPEND) { return NUSE_MAILBOX_FULL; } else { // 메일박스가 비워질 때까지 태스크 일시 중단 } } while (suspend == NUSE_SUSPEND);
요약하면, 메일박스 API는 단순성과 유연성을 균형 있게 제공하여 애플리케이션의 타이밍 요구사항에 따라 즉시 실패 또는 태스크 일시 중단 중 선택할 수 있게 합니다.