[Embedded] Embedded Operating System
OS가 없으면 프로그래머가 무한루프로 직접 순서를 정해야 하지만, OS가 있으면 스케줄러가 자동으로 태스크를 실행해 멀티태스킹을 구현할 수 있다.
무한루프 + 인터럽트 구조는 OS가 없는 상황에서 사용하는 코딩 컨벤션이다.
OS 가 있으면 이렇게 짤 필요가 없다. 여러 함수를 동시에 돌리는 것처럼 보이는 구조를 다룬다.
윈도우나 리눅스에서는 Process와 Thread를 나눠서 부르지만, 임베디드 OS에서는 Task라고 부른다.
어차피 모든 Task가 메모리 공간을 공유하니 Process와 Thread의 구분이 중요하지 않음.

OS 공부할때랑 정말 비슷한.. 임베디드 OS도 일단 근본은 OS니까..
커널은 OS로 애플리케이션에 서비스를 제공한다.
API는 OS와 라이브러리에서 제공하는 인터페이스 함수이고, BSP는 특정 타겟 보드와 연관된 지원코드를 의미한다.
개발자가 작성한 코드는 모두 Application 레벨에서 실행됨.
OS가 없는 시스템에서는 RTOS Kernel과 API층이 비어있다. Application이 Device Driver를 직접 호출한다.
다만 OS 가 있으면 Application과 Driver사이에 OS가 끼어들어서 자원 관리를 대신해준다.
다른 보드로 옮기더라도 Application 코드와 API 호출은 그대로 유지하고, BSP와 Device Driver만 보드에 맞춰서 교체할 수 있음.
임베디드 시스템에 OS가 없는 경우도 있다. 이런 경우 무한루프 안에서 작업을 여러 개의 Task함수로 나눠서 순서대로 실행함.
인터럽트 핸들러는 우선순위가 높은 효과를 가지면서 작업을 수행한다. (Foreground / Background)
다만 메인 루프 안에서의 여러 Task들은 모두 같은 우선순위를 가지게 된다.
/* Background */
void main(void)
{
Initialization;
FOREVER {
Read analog inputs;
Read discrete inputs;
Perform monitoring functions;
Perform control functions;
Update analog outputs;
Update discrete outputs;
Scan keyboard;
Handle user interface;
Update display;
Handle communication requests;
Other...
}
}
/* Foreground */
ISR(void)
{
Handle asynchronous event;
}
모든 Task가 평등하고 지연 발생 시 모든 작업이 함께 멈추게 된다.
STM32F429는 싱글코어로, Cortex-M4 위에서 돌아가는 FreeRTOS는 Concurrent 멀티태스킹을 수행한다.
Parallel 이 아님.. Task를 교대로 실행하는 방식으로 멀티태스킹을 흉내낸다.
OS는 추상화를 제공한다. 각 Task가 자기 혼자 CPU를 독점하는 것 처럼 느끼게 함.
Task는 다른 Task의 존재를 신경쓰지 않아도 됨. 어차피 OS가 다 해준다.

CPU 레지스터는 하나밖에 없지만 OS는 다수의 Task Context를 교대로 선택해서 CPU를 사용하게 한다.
다만 Task마다 자기 스택을 가져야 하니 메모리 비용이 발생함. Task를 너무 많이 만들면 메모리가 부족해진다.
메모리가 매우 부족한 경우 각 필요한 만큼 CPU를 독점해서 실행시키는 협력형이 사용되지만, 웬만하면 CPU 시간을 Time Slice로 배분하는 선점형 방식을 사용한다. (타이머 인터럽트 사용)
void Task1(void *p) {
while(1) { 일하기(); vTaskDelay(100); } // ← Task마다 자기 무한 루프
}
void Task2(void *p) {
while(1) { 일하기(); vTaskDelay(50); }
}
void Task3(void *p) {
while(1) { 일하기(); vTaskDelay(200); }
}
void main(void) {
xTaskCreate(Task1, ...); // ← Task 등록만
xTaskCreate(Task2, ...);
xTaskCreate(Task3, ...);
vTaskStartScheduler(); // ← OS에게 맡김
// main은 여기서 끝. 이후엔 OS가 모든 걸 관리
}
OS가 도입되면 소스코드를 이런 식으로 작성함. Task마다 무한루프가 작성되고 실행 순서는 OS가 결정한다.
인터럽트 핸들러인 ISR은 항상 가장 높은 순위를 가지고, 모든 Task의 실행을 중단시킨다.
Task의 우선순위는 여러 단계 있지만 ISR은 그 무조건 우선시된다.
FreeRTOS는 임베디드 환경을 위한 실시간 내장형 운영체제로, 단순하고 여러 CPU에서 돌릴 수 있다.
소스코드가 4000줄 미만임 (주석제외 로직만)
멀티태스킹을 제공하니 여러 Task간 충돌이 발생할 수 있다.
충돌을 막기 위해 Queue, Semaphore, Mutex 세 가지를 사용함.
큐는 Task간 데이터를 주고받을 때 사용하고, Semaphore는 다수의 쓰레드가 다수의 자원을 접근하는 방법을 제어한다.
Mutex도 마찬가지.. 그런데 OS에서 이미 다 다룬 내용이긴 함.

FreeRTOS 구조는 그림과 같음. CPU 독립 부분과 CPU 의존 부분으로 구분된다.
Hardware Abstraction Layer 덕분에 새로운 CPU를 지원하려면 Port.c 부분만 새로 작성하면 된다.
TickType_t, BaseType_t 같은 자체 자료형을 정의한다.
C언어의 int 자료형은 CPU마다 다르니 같은 코드가 다르게 동작할 수 있음. 그러니 명시적으로 크기를 정한 자료형을 따로 만드는게 임베디드 코딩의 표준이다.
FreeRTOS API List에서 지원하는 기능을 카테고리별로 확인할 수 있으니 필요할 때 확인하자.
스케쥴러는 ticks에 따라 CPU 시간을 태스크에 할당하고, OS의 매 Tick Interupt마다 Kernel은 다음에 할 일을 결정한다.
OS를 사용하면 Timer하나는 OS 전용으로 사용된다. 그러니 TIM3 TIM4 TIM10 등.. 여러 Timer 중 하나는 OS 전용이 됨.
OS의 모든 시간 흐름은 SysTick에서 시작되고, 스케쥴러를 호출하고 Ready Task 중 가장 높은 우선순위를 선택하고 실행하는 사이클이 계속해서 반복된다.
int main(void)
{
xTaskCreate(
vTask1, // ① 태스크 함수 포인터
"Task 1", // ② 디버깅용 이름
1000, // ③ 스택 크기 (words)
NULL, // ④ 태스크에 전달할 파라미터
1, // ⑤ 우선순위
NULL ); // ⑥ 태스크 핸들 (반환)
xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
vTaskStartScheduler(); // OS 시작
}
void vTask1(void *pvParameters)
{
const char *pcTaskName = "Task 1 is running\r\n";
volatile unsigned long ul;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
vPrintString(pcTaskName);
/* Delay for a period. */
for(ul = 0; ul < mainDELAY_LOOP_COUNT; ul++)
{
/* crude delay implementation */
}
}
}
1. Task 함수 2개 만들기
2. xTaskCreate 호출해서 우선순위 Task 생성
3. vTaskStartScheduler로 스케쥴러 실행
이 세 단계가 FreeRTOS 프로그래밍의 기본 패턴이다.

동일한 우선순위는 Tick Interrupt 서비스에 따라 라운드 로빈 방식으로 실행이 바뀐다.
우선순위가 다른 경우이더라도, Task가 일을 하지 않을 때는 자발적으로 CPU를 양보하는 구조를 작성해야 한다.
Busy Waiting방식을 사용하기도 하지만.. vTaskDelay(x)API를 호출해 현재 태스크를 X Tick만큼 지연시키는 방식이 더 합리적이다.
Busy Waiting은 CPU를 계속 점유하면서 다른 Task를 차단해 높은 우선순위의 Task만 실행될 수 있지만, vTaskDelay 방식은 낮은 우선순위 Task도 실행될 기회를 얻는다.
'Computer Science > Embedded Software' 카테고리의 다른 글
| [Embedded] Device Driver (0) | 2026.05.14 |
|---|---|
| [Embedded] Motor (0) | 2026.05.13 |
| [Embedded] Sensor (0) | 2026.05.13 |
| [Embedded] Communication Programming (0) | 2026.05.12 |
| [Embedded] Communication Protocol (1) (0) | 2026.05.12 |
댓글
이 글 공유하기
다른 글
-
[Embedded] Device Driver
[Embedded] Device Driver
2026.05.14 -
[Embedded] Motor
[Embedded] Motor
2026.05.13 -
[Embedded] Sensor
[Embedded] Sensor
2026.05.13 -
[Embedded] Communication Programming
[Embedded] Communication Programming
2026.05.12