# 실습과 실험

#### 실습의 필요성

Xenomai에 대한 실습은 이론적인 지식과는 별도로 실제 경험을 통해 이해를 돕고 문제 해결 능력을 향상시키는 데 필수적이다. 실습을 통해 실무에서 마주할 수 있는 다양한 문제들을 미리 경험하고, 이를 해결하는데 필요한 기술과 지식을 얻을 수 있다. 따라서, 실제 시스템에서 Xenomai를 사용할 수 있도록 실습 환경을 구성하고, 구체적인 문제를 해결하는 과정을 통해 학습하는 것이 중요하다.

#### 실습 환경 설정

**하드웨어 요구 사항**

Xenomai를 실습하기 위해서는 특정한 하드웨어가 필요하다. 다음과 같은 사항을 준비해야 한다:

* **컴퓨터**: Xenomai를 설치할 수 있는 데스크탑 또는 노트북
* **마이크로컨트롤러 보드**: Xenomai와 연동 가능한 보드 (예: BeagleBone Black, Raspberry Pi 등)
* **기타 주변기기**: 필요한 경우 추가적인 센서나 액추에이터

**소프트웨어 요구 사항**

실습을 진행하기 위해 필요한 소프트웨어는 다음과 같다:

* **운영체제**: Xenomai를 지원하는 Linux 배포판
* **컴파일러**: GCC와 같은 C/C++ 컴파일러
* **Xenomai 패키지**: Xenomai 설치 패키지와 관련 툴체인

#### 기본 실습: 간단한 실시간 태스크 생성

다음으로, 기본적인 실시간 태스크를 생성하는 실습을 진행한다. 이는 Xenomai의 기본 기능을 이해하는 데 필수적인 단계이다.

**코드 예제: 간단한 실시간 태스크**

다음은 간단한 실시간 태스크를 생성하는 예제 코드이다:

```c
#include <stdio.h>
#include <alchemy/task.h>

RT_TASK my_task;

void my_task_func(void *arg) {
    while (1) {
        printf("Real-time task is running!\n");
        rt_task_sleep(1000000000); // Sleep for 1 second
    }
}

int main(int argc, char *argv[]) {
    rt_task_create(&my_task, "MyTask", 0, 50, 0);
    rt_task_start(&my_task, &my_task_func, NULL);

    pause(); // Keep the program running
    return 0;
}
```

**코드 설명**

* `rt_task_create(&my_task, "MyTask", 0, 50, 0);`: 이름이 "MyTask"인 태스크를 생성한다. 이 태스크는 우선순위 50으로 설정된다.
* `rt_task_start(&my_task, &my_task_func, NULL);`: 생성된 태스크를 시작하고, 함수 `my_task_func`를 실행한다.
* `rt_task_func(void *arg)`: 반복적으로 "Real-time task is running!"을 출력하고, 1초 동안 슬립하는 간단한 함수이다.

#### 응용 실습: 실시간 데이터 처리

보다 복잡한 상황을 처리하기 위해, 실시간 데이터 처리를 위한 실습을 진행한다. 이는 센서 데이터 수집 및 처리와 같은 응용에서 유용하다.

**코드 예제: 실시간 데이터 수집 및 처리**

다음 예제는 실시간 데이터를 수집하고 처리하는 방식이다:

```c
#include <stdio.h>
#include <alchemy/task.h>
#include <alchemy/alarm.h>
#include <alchemy/heap.h>
#include <stdint.h>

#define DATA_SIZE 10

RT_TASK data_task;
RT_HEAP data_heap;
RT_ALARM data_alarm;
int16_t data_array[DATA_SIZE];

void process_data(int16_t *data) {
    for (int i = 0; i < DATA_SIZE; i++) {
        data[i] = data[i] * 2; // 예: 데이터 가공 (간단히 두 배로)
    }
}

void data_task_func(void *arg) {
    int16_t *heap_data;
    rt_heap_bind(&data_heap, "dataHeap", TM_INFINITE);
    rt_heap_alloc(&data_heap, sizeof(int16_t) * DATA_SIZE, TM_INFINITE, (void **)&heap_data);

    while (1) {
        for (int i = 0; i < DATA_SIZE; i++) {
            heap_data[i] = rand() % 100; // 예: 가상 센서 데이터 수집
        }
        process_data(heap_data);
        rt_task_sleep(1000000000); // 1초 동안 슬립
    }
}

int main(int argc, char *argv[]) {
    rt_heap_create(&data_heap, "dataHeap", sizeof(int16_t) * DATA_SIZE, H_SHARED);
    rt_task_create(&data_task, "DataTask", 0, 50, 0);
    rt_task_start(&data_task, &data_task_func, NULL);

    pause(); // 프로그램을 종료하지 않도록 유지
    return 0;
}
```

**코드 설명**

* **데이터 배열과 힙**: `data_array`는 데이터를 저장할 배열이며, `data_heap`은 Xenomai의 실시간 힙을 사용하여 데이터를 공유한다.
* **데이터 처리 함수**: `process_data`는 배열의 각 요소를 두 배로 만드는 간단한 데이터 처리 함수이다.
* **실시간 태스크**: `data_task_func`는 매 1초마다 가상의 센서 데이터를 수집하여 데이터를 처리한다.
* **힙 할당**: `rt_heap_alloc`를 통해 공유 힙에서 데이터를 수집하고 처리한다.

#### 실습 결과 분석

실습을 통해 얻은 데이터를 분석하고 결과를 도출하기 위한 방법도 중요하다. 다음은 실습 결과를 분석하는 몇 가지 방법이다:

**1. 로그 파일 분석**

실시간 태스크의 실행 로그를 파일에 저장하고, 이를 분석하여 시스템의 실시간 성능을 평가한다.

**2. 성능 메트릭 계측**

실시간 태스크의 주기, 응답 시간, 지연 시간 등의 메트릭을 계측하여 Xenomai의 성능을 평가한다.

**3. 그래프와 시각화 도구 사용**

수집된 데이터를 그래프로 시각화하여 직관적으로 이해할 수 있다. 그래프는 실시간 성능, 태스크 교체 빈도, 데이터 처리량 등을 효과적으로 보여준다.

#### 고급 실습: 하드웨어 인터페이스

마지막으로, Xenomai를 사용하여 하드웨어와 인터페이스하는 실습을 진행한다. 이는 실제 프로젝트에서의 응용성을 높이는 데 도움이 된다.

**예제: GPIO 제어**

다음은 GPIO를 제어하는 예제 코드이다:

```c
#include <stdio.h>
#include <alchemy/task.h>
#include <alchemy/sem.h>
#include <wiringPi.h>

#define PIN 7

RT_TASK gpio_task;
RT_SEM sem;

void gpio_task_func(void *arg) {
    while (1) {
        rt_sem_p(&sem, TM_INFINITE);
        digitalWrite(PIN, HIGH);
        rt_task_sleep(500000000); // 0.5초 슬립
        digitalWrite(PIN, LOW);
        rt_task_sleep(500000000); // 0.5초 슬립
    }
}

int main(int argc, char *argv[]) {
    wiringPiSetup(); // GPIO 설정
    pinMode(PIN, OUTPUT);

    rt_sem_create(&sem, "Sem", 0, S_PRIO);
    rt_task_create(&gpio_task, "GPIOTask", 0, 50, 0);
    rt_task_start(&gpio_task, &gpio_task_func, NULL);

    while (1) {
        rt_sem_v(&sem); // 세마포어 신호 전송
        rt_task_sleep(2000000000); // 2초 슬립 후 다시 신호
    }

    return 0;
}
```

**코드 설명**

* `wiringPiSetup`과 `pinMode`: GPIO 핀을 초기화하고 출력 모드로 설정한다.
* `gpio_task_func`: GPIO 핀을 주기적으로 on/off 하는 실시간 태스크이다.
* `rt_sem_create`와 `rt_sem_v`: 세마포어를 사용하여 태스크를 제어한다.

위 실습들을 통해 Xenomai의 주요 기능과 활용 방안을 학습할 수 있으며, 실무에서 Xenomai를 사용하는 데 필요한 경험을 쌓을 수 있다.
