FreeRTOS 커널 기초 - 무료 RTOS

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

FreeRTOS 커널 기초

FreeRTOS 커널은 다양한 아키텍처를 지원하는 실시간 운영 체제이며, 내장형 마이크로 컨트롤러 애플리케이션을 빌드하는 데 적합합니다. 이 커널은 다음을 제공합니다.

  • 멀티태스킹 스케줄러

  • 다중 메모리 할당 옵션(완전히 정적으로 할당되는 시스템 생성 기능 포함)

  • 작업 간 조정 프리미티브(작업 알림, 메시지 대기열, 다양한 유형의 세마포어, 스트림 및 메시지 버퍼 포함)

  • 멀티코어 마이크로컨트롤러의 대칭적 다중 처리(SMP) 지원

FreeRTOS 커널에서는 중요 섹션 또는 인터럽트 내에서 연결된 목록 검색과 같은 비결정적 작업을 수행하지 않습니다. FreeRTOS 커널에는 타이머에 서비스가 필요한 경우에만 CPU 시간을 사용하는 효과적인 소프트웨어 타이머 구현이 포함되어 있습니다. 차단된 작업에는 시간이 많이 소요되는 주기적 서비스가 필요하지 않습니다. DTT(Direct-to-Task) 알림을 사용하면 RAM 오버헤드 없이 작업 신호를 빠르게 전송할 수 있습니다. 대부분의 작업 간 및 작업 중단 신호 전송 시나리오에서 DTT 알림을 사용할 수 있습니다.

FreeRTOS 커널은 작고 간단하고 사용하기 쉽게 설계되었습니다. 일반 RTOS 커널 이진 이미지는 4000~9000바이트 범위 내에 있습니다.

FreeRTOS 커널에 대한 최신 문서는 FreeRTOS.org를 방문하세요. FreeRTOS.org에서는 Quick Start Guide 및 상세한 Mastering the FreeRTOS Real Time Kernel을 비롯하여, FreeRTOS 커널 사용에 대한 자세한 자습서와 안내서를 다양하게 제공합니다.

FreeRTOS 커널 스케줄러

RTOS를 사용하는 내장형 애플리케이션을 독립된 작업 세트로 구성할 수 있습니다. 각 작업은 다른 작업에 종속되지 않고 자체 컨텍스트 내에서 실행됩니다. 애플리케이션에서는 한 번에 하나의 작업만 실행합니다. 실시간 RTOS 스케줄러에 따라 각 작업이 실행되는 시간이 결정됩니다. 각 작업에는 자체 스택이 제공됩니다. 다른 작업을 실행할 수 있도록 작업을 스왑하면 작업의 실행 컨텍스트가 작업 스택에 저장됩니다. 따라서 나중에 해당 작업을 재개하기 위해 다시 스왑하면 실행 컨텍스트가 복원됩니다.

결정적인 실시간 동작을 제공하려면 FreeRTOS 작업 스케줄러를 사용하여 작업에 엄격한 우선 순위를 할당할 수 있습니다. RTOS를 사용하면 실행 가능한 작업 중 우선 순위가 가장 높은 작업에 처리 시간이 제공됩니다. 따라서 우선 순위가 동일한 여러 작업이 동시에 실행 준비가 될 경우 작업 간에 처리 시간을 공유해야 합니다. 또한 FreeRTOS에서는 실행 준비된 다른 작업이 없는 경우에만 실행되는 유휴 작업을 생성합니다.

메모리 관리

이 단원에서는 커널 메모리 할당 및 애플리케이션 메모리 관리에 대한 정보를 제공합니다.

커널 메모리 할당

RTOS 커널에서는 작업, 대기열 또는 다른 RTOS 객체가 생성될 때마다 RAM이 필요합니다. RAM을 다음과 같이 할당할 수 있습니다.

  • 컴파일 시간에 정적으로

  • RTOS API 객체 생성 함수를 사용하여 RTOS 힙에서 동적으로

RTOS 객체를 동적으로 생성하는 경우 다음과 같은 여러 가지 이유로 인해 표준 C 라이브러리 malloc()free() 함수를 사용하는 것이 적절하지 않은 경우도 있습니다.

  • 내장형 시스템에서 사용할 수 없습니다.

  • 중요한 코드 공간을 차지합니다.

  • 일반적으로 스레드 세이프가 아닙니다.

  • 결정적이지 않습니다.

따라서 FreeRTOS는 이동형 계층에 메모리 할당 API를 보관합니다. 이동형 계층은 코어 RTOS 기능을 구현하는 소스 파일의 외부에 있으므로, 개발 중인 실시간 시스템에 적절한 애플리케이션별 구현을 제공할 수 있습니다. RTOS 커널은 RAM이 필요한 경우 malloc() 대신 pvPortMalloc()를 호출합니다. RAM을 비우고 있는 경우 RTOS 커널은 free() 대신 vPortFree()를 호출합니다.

애플리케이션 메모리 관리

애플리케이션에 메모리가 필요한 경우 FreeRTOS 힙에서 메모리를 할당할 수 있습니다. FreeRTOS는 복잡성과 기능이 요구되는 다양한 힙 관리 스키마를 제공합니다. 사용자가 고유한 힙 구현을 제공할 수도 있습니다.

FreeRTOS 커널에는 5가지 힙 구현이 포함되어 있습니다.

heap_1

가장 간단한 구현입니다. 메모리를 비울 수 없습니다.

heap_2

메모리를 비울 수 있지만, 사용 가능한 인접 블록을 결합하지 않습니다.

heap_3

스레드 안전을 위해 표준 malloc()free()를 래핑합니다.

heap_4

사용 가능한 인접 블록을 결합하여 조각화 현상을 방지합니다. 절대 주소 배치 옵션을 포함합니다.

heap_5

heap_4와 유사합니다. 힙이 인접하지 않은 여러 메모리 영역에 걸쳐서 존재할 수 있습니다.

작업 간 조정

이 단원에는 FreeRTOS 프리미티브에 대한 정보가 포함되어 있습니다.

대기열

대기열은 기본적인 형태의 작업 간 통신입니다. 대기열을 사용하여 작업 간이나 인터럽트와 작업 간에 메시지를 전송할 수 있습니다. 대부분의 경우 대기열은 스레드 세이프(thread-safe) FIFO(First In First Out) 버퍼로 사용되며, 새로운 데이터는 대기열의 뒤쪽으로 전송됩니다. 데이터가 대기열의 앞쪽으로 전송될 수도 있습니다. 메시지는 대기열을 통해 복사본으로 전송됩니다. 즉, 단순히 데이터에 대한 참조를 저장하지 않고 데이터(더 큰 버퍼에 대한 포인터일 수 있음)를 대기열에 복사합니다.

대기열 API는 블록 시간 지정을 허용합니다. 특정 작업이 빈 대기열에서 읽으려고 시도할 경우 대기열에서 데이터를 사용할 수 있거나 블록 시간이 경과할 때까지 해당 작업은 차단 상태로 전환됩니다. 다른 작업이 실행될 수 있도록 차단 상태인 작업은 CPU 시간을 사용하지 않습니다. 마찬가지로, 특정 작업이 전체 대기열에서 쓰려고 시도할 경우 대기열의 공간이 사용 가능해지거나 블록 시간이 경과할 때까지 해당 작업은 차단 상태로 전환됩니다. 동일한 대기열에 차단된 작업이 여러 개 있는 경우 우선 순위가 가장 높은 작업이 먼저 차단 해제됩니다.

다른 FreeRTOS 프리미티브(예: DTT(Direct-to-Task) 알림, 스트림 및 메시지 버퍼)는 다양한 일반 설계 시나리오에서 대기열에 대한 간단한 대안을 제공합니다.

세마포어 및 뮤텍스

FreeRTOS 커널은 상호 제외와 동기화의 목적으로 이진 세마포어, 계수 세마포어 및 뮤텍스를 제공합니다.

이진 세마포어는 두 개의 값만 가질 수 있습니다. 이 세마포어는 작업 간이나 작업과 인터럽트 간에 동기화를 구현하는 데 적합합니다. 계수 세마포어는 세 개 이상의 값을 가집니다. 계수 세마포어를 사용하면 여러 작업에서 리소스를 공유하거나 보다 복잡한 동기화 작업을 수행할 수 있습니다.

뮤텍스는 우선 순위 상속 메커니즘을 포함하는 이진 세마포어입니다. 즉, 우선 순위가 높은 작업이 현재 우선 순위가 낮은 작업에서 보유한 뮤텍스를 가져오려고 시도하는 동안 차단될 경우 토큰을 보유한 작업의 우선 순위가 차단된 작업의 우선 순위로 일시적으로 상승됩니다. 이 메커니즘은 우선 순위가 더 높은 작업이 차단 상태로 유지되는 시간을 최대한 단축하여 우선 순위 반전이 발생하는 것을 최소화하기 위해 설계되었습니다.

DTT 알림

작업 알림을 사용하면 세마포어와 같은 개별 통신 객체 없이 작업 간에 상호 작용하고, 인터럽트 서비스 루틴(ISR)과 동기화할 수 있습니다. 각 RTOS 작업에는 알림 내용(있는 경우)을 저장하는 데 사용되는 32비트 알림 값이 있습니다. RTOS 작업 알림은 수신 작업을 차단 해제하고 수신 작업의 알림 값을 선택적으로 업데이트할 수 있는 작업에 직접 전송되는 이벤트입니다.

RTOS 작업 알림을 이진 세마포어, 계수 세마포어 및 대기열(해당하는 경우)에 대한 더 빠르고 간단한 대안으로 사용할 수 있습니다. 작업 알림은 동일한 기능을 수행하는 데 사용될 수 있는 다른 FreeRTOS 기능에 비해 속도와 RAM 공간의 측면에서 이점이 있습니다. 하지만 작업 알림은 이벤트 수신자가 될 수 있는 작업이 하나뿐인 경우에만 사용될 수 있습니다.

스트림 버퍼

스트림 버퍼를 사용하면 바이트 스트림을 인터럽트 서비스 루틴에서 작업으로 또는 한 작업에서 다른 작업으로 전달할 수 있습니다. 바이트 스트림은 임의 길이를 가질 수 있으며 시작 또는 끝이 없어도 됩니다. 한 번에 쓰고 읽을 수 있는 바이트 수에 제한이 없습니다. 프로젝트에서 stream_buffer.c 소스 파일을 포함하여 스트림 버퍼 기능을 활성화합니다.

스트림 버퍼를 사용하면 버퍼에 쓰는 작업 또는 인터럽트 하나(라이터)와 버퍼에서 읽는 작업 또는 인터럽트 하나(리더)만 존재합니다. 라이터와 리더의 작업 또는 인터럽트 서비스 루틴이 달라도 되지만 여러 라이터 또는 리더가 존재하면 안 됩니다.

스트림 버퍼 구현에서는 DTT 알림을 사용합니다. 따라서 호출 작업을 차단 상태로 전환하는 스트림 버퍼 API를 호출하면 호출 작업의 알림 상태와 값이 변경될 수 있습니다.

데이터 전송

xStreamBufferSend()는 데이터를 작업 내 스트림 버퍼로 전송하는 데 사용되고, xStreamBufferSendFromISR()은 데이터를 인터럽트 서비스 루틴(ISR) 내 스트림 버퍼로 전송하는 데 사용됩니다.

xStreamBufferSend()는 블록 시간 지정을 허용합니다. xStreamBufferSend()가 스트림 버퍼에 쓰기 위해 0이 아닌 블록 시간으로 호출되고 버퍼가 꽉 찬 경우 공간을 사용할 수 있거나 블록 시간이 만료될 때까지 작업은 차단 상태로 전환됩니다.

sbSEND_COMPLETED()sbSEND_COMPLETED_FROM_ISR()은 스트림 버퍼에 데이터를 쓸 때 FreeRTOS API에 의해 내부적으로 호출되는 매크로입니다. 이 매크로는 업데이트된 스트림 버퍼의 핸들을 사용합니다. 두 매크로는 모두 스트림 버퍼에 데이터를 대기 중인 차단된 작업이 있는지 확인한 후, 있으면 해당 작업을 차단 상태에서 제거합니다.

FreeRTOSConfig.h에서 sbSEND_COMPLETED()의 자체 구현을 제공하여 이 기본 동작을 변경할 수 있습니다. 이 기능은 스트림 버퍼를 사용하여 멀티 코어 프로세서의 코어 간에 데이터를 전달할 때 유용합니다. 그러한 시나리오에서는 sbSEND_COMPLETED()를 구현하여 다른 CPU 코어에서 인터럽트를 생성한 다음 인터럽트의 서비스 루틴에서 xStreamBufferSendCompletedFromISR() API를 사용하여 데이터를 대기 중인 작업이 있는지 확인하고 필요한 경우 해당 작업을 차단 해제할 수 있습니다.

데이터 수신

xStreamBufferReceive()는 작업 내 스트림 버퍼에서 데이터를 읽는 데 사용되고, xStreamBufferReceiveFromISR()은 인터럽트 서비스 루틴(ISR) 내 스트림 버퍼에서 데이터를 읽는 데 사용됩니다.

xStreamBufferReceive()는 블록 시간 지정을 허용합니다. xStreamBufferReceive()가 스트림 버퍼에서 읽기 위해 0이 아닌 블록 시간으로 호출되고 버퍼가 비어 있는 경우 스트림 버퍼에서 지정된 양의 데이터를 사용할 수 있거나 블록 시간이 만료될 때까지 작업은 차단 상태로 전환됩니다.

작업이 차단 해제되기 전에 스트림 버퍼에 있어야 하는 데이터의 양을 스트림 버퍼의 트리거 수준이라고 합니다. 트리거 수준 10으로 차단된 작업은 버퍼에 10바이트 이상을 쓰거나 작업의 블록 시간이 만료될 때 차단 해제됩니다. 트리거 수준에 도달하기 전에 읽기 작업의 블록 시간이 만료될 경우 해당 작업은 버퍼에 기록된 데이터를 수신합니다. 작업의 트리거 수준을 1과 스트림 버퍼 크기 사이의 값으로 설정해야 합니다. 스트림 버퍼의 트리거 수준은 xStreamBufferCreate()를 호출할 때 설정됩니다. xStreamBufferSetTriggerLevel()를 호출하여 트리거 수준을 변경할 수 있습니다.

sbRECEIVE_COMPLETED()sbRECEIVE_COMPLETED_FROM_ISR()은 스트림 버퍼에서 데이터를 읽을 때 (FreeRTOS API에 의해 내부적으로) 호출되는 매크로입니다. 이 매크로는 버퍼 내에서 공간을 사용할 수 있을 때까지 대기하는 스트림 버퍼에 차단된 작업이 있는지 확인한 후 있는 경우 해당 작업을 차단 상태에서 제거합니다. FreeRTOSConfig.h에서 대체 구현을 제공하여 sbRECEIVE_COMPLETED()의 기본 동작을 변경할 수 있습니다.

메시지 버퍼

메시지 버퍼를 사용하면 인터럽트 서비스 루틴에서 작업으로 또는 한 작업에서 다른 작업으로 가변 길이의 별도 메시지를 전달할 수 있습니다. 예를 들어, 길이가 10, 20 및 123바이트인 메시지를 모두 동일한 메시지 버퍼에서 쓰고 읽을 수 있습니다. 10바이트 메시지는 개별 바이트가 아닌 10바이트 메시지로만 읽을 수 있습니다. 메시지 버퍼는 스트림 버퍼 구현을 기반으로 빌드됩니다. 프로젝트에서 stream_buffer.c 소스 파일을 포함하여 메시지 버퍼 기능을 활성화할 수 있습니다.

메시지 버퍼를 사용하면 버퍼에 쓰는 작업 또는 인터럽트 하나(라이터)와 버퍼에서 읽는 작업 또는 인터럽트 하나(리더)만 존재합니다. 라이터와 리더의 작업 또는 인터럽트 서비스 루틴이 달라도 되지만 여러 라이터 또는 리더가 존재하면 안 됩니다.

메시지 버퍼 구현에서는 DTT 알림을 사용합니다. 따라서 호출 작업을 차단 상태로 전환하는 스트림 버퍼 API를 호출하면 호출 작업의 알림 상태와 값이 변경될 수 있습니다.

메시지 버퍼를 사용하여 가변 크기 메시지를 처리하려면 각 메시지의 길이가 메시지보다 먼저 메시지 버퍼에 기록됩니다. 길이는 size_t 형식의 변수로 저장되며, 32바이트 아키텍처의 경우 일반적으로 4바이트입니다. 따라서 메시지 버퍼에 10바이트 메시지를 쓸 경우 실제로 14바이트의 버퍼 공간이 사용됩니다. 마찬가지로 메시지 버퍼에 100바이트 메시지를 쓸 경우 실제로 104바이트의 버퍼 공간이 사용됩니다.

데이터 전송

xMessageBufferSend()는 작업에서 메시지 버퍼로 전송하는 데 사용되고, xMessageBufferSendFromISR()은 인터럽트 서비스 루틴(ISR)에서 메시지 버퍼로 데이터를 전송하는 데 사용됩니다.

xMessageBufferSend()는 블록 시간 지정을 허용합니다. xMessageBufferSend()가 메시지 버퍼에 쓰기 위해 0이 아닌 블록 시간으로 호출되고 버퍼가 꽉 찬 경우 메시지 버퍼에서 공간을 사용할 수 있거나 블록 시간이 만료될 때까지 작업은 차단 상태로 전환됩니다.

sbSEND_COMPLETED()sbSEND_COMPLETED_FROM_ISR()은 스트림 버퍼에 데이터를 쓸 때 FreeRTOS API에 의해 내부적으로 호출되는 매크로입니다. 이 매크로는 단일 파라미터 즉, 업데이트된 스트림 버퍼의 핸들을 사용합니다. 두 매크로는 모두 스트림 버퍼에 데이터를 대기 중인 차단된 작업이 있는지 확인한 후, 있으면 해당 작업을 차단 상태에서 제거합니다.

FreeRTOSConfig.h에서 sbSEND_COMPLETED()의 자체 구현을 제공하여 이 기본 동작을 변경할 수 있습니다. 이 기능은 스트림 버퍼를 사용하여 멀티 코어 프로세서의 코어 간에 데이터를 전달할 때 유용합니다. 그러한 시나리오에서는 sbSEND_COMPLETED()를 구현하여 다른 CPU 코어에서 인터럽트를 생성한 다음 인터럽트의 서비스 루틴에서 xStreamBufferSendCompletedFromISR() API를 사용하여 데이터를 대기 중인 작업이 있는지 확인하고 필요한 경우 해당 작업을 차단 해제할 수 있습니다.

데이터 수신

xMessageBufferReceive()는 작업에서 메시지 버퍼의 데이터를 읽는 데 사용되고, xMessageBufferReceiveFromISR()은 인터럽트 서비스 루틴(ISR)에서 메시지 버퍼의 데이터를 읽는 데 사용됩니다. xMessageBufferReceive()는 블록 시간 지정을 허용합니다. xMessageBufferReceive()가 메시지 버퍼에서 읽기 위해 0이 아닌 블록 시간으로 호출되고 버퍼가 비어 있는 경우 데이터를 사용할 수 있거나 블록 시간이 만료될 때까지 작업은 차단 상태로 전환됩니다.

sbRECEIVE_COMPLETED()sbRECEIVE_COMPLETED_FROM_ISR()은 스트림 버퍼에서 데이터를 읽을 때 (FreeRTOS API에 의해 내부적으로) 호출되는 매크로입니다. 이 매크로는 버퍼 내에서 공간을 사용할 수 있을 때까지 대기하는 스트림 버퍼에 차단된 작업이 있는지 확인한 후 있는 경우 해당 작업을 차단 상태에서 제거합니다. FreeRTOSConfig.h에서 대체 구현을 제공하여 sbRECEIVE_COMPLETED()의 기본 동작을 변경할 수 있습니다.

대칭적 다중 처리(SMP) 지원

FreeRTOS 커널의 SMP 지원을 통해 하나의 FreeRTOS 커널 인스턴스가 여러 개의 동일한 프로세서 코어에 걸쳐 태스크를 예약할 수 있습니다. 코어 아키텍처는 동일해야 하며 동일한 메모리를 공유해야 합니다.

FreeRTOS-SMP 커널을 사용하도록 애플리케이션 수정

FreeRTOS API는 이러한 추가 API를 제외하고 싱글 코어 버전과 SMP 버전 간에 거의 동일하게 유지됩니다. 따라서 FreeRTOS 싱글 코어 버전용으로 작성된 애플리케이션은 최소한의 노력을 들여 SMP 버전으로 컴파일해야 합니다. 하지만 싱글 코어 애플리케이션에 적용되던 일부 가정이 멀티 코어 애플리케이션에서는 더 이상 유효하지 않을 수 있기 때문에 일부 기능적 문제가 있을 수 있습니다.

한 가지 일반적인 가정은 우선 순위가 높은 작업이 실행되는 동안에는 우선 순위가 낮은 작업을 실행할 수 없다는 것입니다. 이는 단일 코어 시스템에서는 맞는 가정이지만 멀티 코어 시스템에서는 여러 태스크를 동시에 실행할 수 있기 때문에 더 이상 그렇지 않습니다. 애플리케이션이 상대적인 태스크 우선 순위에 의존하여 상호 배제를 적용하는 경우 멀티 코어 환경에서 예상치 못한 결과가 발생할 수 있습니다.

또 다른 일반적인 가정은 ISR을 서로 또는 다른 태스크와 동시에 실행할 수 없다는 것입니다. 멀티코어 환경에서는 더 이상 그렇지 않습니다. 애플리케이션 작성자는 태스크와 ISR 간에 공유되는 데이터에 액세스하는 동안 적절한 상호 배제를 보장해야 합니다.

소프트웨어 타이머

소프트웨어 타이머를 사용하여 이후의 설정된 시간에 함수를 실행할 수 있습니다. 타이머에 의해 실행되는 함수를 타이머의 콜백 함수라고 합니다. 타이머가 시작되는 시간부터 콜백 함수가 실행되는 시간 사이를 타이머 기간이라고 합니다. FreeRTOS 커널이 효과적인 소프트웨어 타이머 구현을 제공하는 이유는 다음과 같습니다.

  • 인터럽트 컨텍스트에서 타이머 콜백 함수를 실행하지 않습니다.

  • 타이머가 실제로 만료되지 않는 한 처리 시간을 사용하지 않습니다.

  • 틱 인터럽트에 처리 오버헤드를 추가하지 않습니다.

  • 인터럽트가 비활성화된 상태에서 링크 목록 구조를 이동하지 않습니다.

저전력 지원

대부분의 임베디드 운영 체제와 마찬가지로 FreeRTOS 커널은 하드웨어 타이머를 사용하여 시간을 측정하는 데 사용되는 주기적 틱 인터럽트를 생성합니다. 틱 인터럽트를 처리하기 위해 저전력 상태를 주기적으로 종료했다가 다시 시작해야 하므로 정기적인 하드웨어 타이머 구현의 절전 효과는 제한됩니다. 틱 인터럽트의 빈도가 너무 높을 경우 모든 틱에 대한 저전력 상태를 시작하고 종료하는 데 사용되는 에너지 및 시간이 최대 절전 모드를 제외한 모든 모드의 잠재적 절전 효과를 능가합니다.

이 제한을 해결하기 위해 FreeRTOS에는 저전력 애플리케이션을 위한 타이머 미작동 모드가 포함되어 있습니다. FreeRTOS 타이머 미작동 유휴 모드에서는 유휴 기간(실행 가능한 애플리케이션 작업이 없는 기간) 동안 주기적으로 틱 인터럽트를 중지한 후, 틱 인터럽트를 다시 시작할 때 RTOS 틱 카운트 값을 알맞게 조정합니다. 틱 인터럽트를 중지하면 인터럽트가 발생하거나 RTOS 커널에서 작업을 준비 상태로 전환할 때까지 마이크로 컨트롤러가 딥 절전 상태로 유지될 수 있습니다.

커널 구성

FreeRTOSConfig.h 헤더 파일을 사용하여 특정 보드 및 애플리케이션에 대해 FreeRTOS 커널을 구성할 수 있습니다. 커널을 기반으로 빌드되는 모든 애플리케이션은 프리프로세서 포함 경로에 FreeRTOSConfig.h 헤더 파일이 있어야 합니다. FreeRTOSConfig.h는 애플리케이션 고유의 파일이며, FreeRTOS 커널 소스 코드 디렉터리 중 하나가 아니라 애플리케이션 디렉터리 아래에 위치해야 합니다.

FreeRTOS 데모 및 테스트 애플리케이션용 FreeRTOSConfig.h 파일은 freertos/vendors/vendor/boards/board/aws_demos/config_files/FreeRTOSConfig.hfreertos/vendors/vendor/boards/board/aws_tests/config_files/FreeRTOSConfig.h에 위치합니다.

FreeRTOSConfig.h에서 지정할 수 있는 구성 파라미터의 목록은 FreeRTOS.org를 참조하십시오.