Linux/yocto

Yocto 애플리케이션 개발

임베디드 친구 2025. 5. 23. 23:34
728x90
반응형

Yocto 애플리케이션 개발

이 글에서는 Yocto 기반으로 Rockchip RK3399 플랫폼에서 애플리케이션을 개발하는 방법을 다룹니다. 특히 GPIO, UART, I2C와 같은 주변 장치를 제어하는 방법과 간단한 웹 서버, 데이터 로깅 애플리케이션을 구현하는 과정을 설명합니다. 이를 통해 실무 환경에서도 활용 가능한 애플리케이션을 작성하는 방법을 익히실 수 있을 것입니다.

1. RK3399 기반 애플리케이션 개발 개요

RK3399는 강력한 성능과 다양한 주변 장치를 지원하는 ARM 기반 프로세서입니다. Yocto 프로젝트를 통해 임베디드 리눅스를 빌드하면 다음과 같은 환경에서 애플리케이션을 개발할 수 있습니다.

  • C/C++ 기반의 네이티브 애플리케이션: 성능 최적화가 필요할 때 유용합니다.
  • Python 기반의 스크립트 애플리케이션: 빠른 개발과 유지보수에 적합합니다.
  • 웹 기반 애플리케이션: 경량 웹 서버와 함께 RESTful API를 제공하는 서비스 개발이 가능합니다.

이 글에서는 C/C++과 Python을 중심으로 주변 장치 제어와 웹 애플리케이션 개발 방법을 설명하겠습니다.


2. GPIO 제어 예제

GPIO는 간단한 신호 제어와 센서 입력을 처리하는 데 사용됩니다. RK3399에서는 sysfs 인터페이스를 통해 GPIO를 제어할 수 있습니다. 다음은 LED를 제어하는 예제입니다.

2.1 C 언어 기반 GPIO 제어 예제

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

#define GPIO_PIN "23"

void write_to_file(const char *path, const char *value) {
    int fd = open(path, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open GPIO file");
        exit(EXIT_FAILURE);
    }
    write(fd, value, sizeof(value));
    close(fd);
}

int main() {
    // GPIO Export
    write_to_file("/sys/class/gpio/export", GPIO_PIN);
    sleep(1);

    // GPIO 방향 설정
    write_to_file("/sys/class/gpio/gpio" GPIO_PIN "/direction", "out");

    // GPIO ON
    write_to_file("/sys/class/gpio/gpio" GPIO_PIN "/value", "1");
    printf("LED ON\n");
    sleep(2);

    // GPIO OFF
    write_to_file("/sys/class/gpio/gpio" GPIO_PIN "/value", "0");
    printf("LED OFF\n");

    // GPIO Unexport
    write_to_file("/sys/class/gpio/unexport", GPIO_PIN);
    return 0;
}

2.2 Python 기반 GPIO 제어 예제

import time

def write_to_file(path, value):
    with open(path, 'w') as f:
        f.write(value)

GPIO_PIN = "23"

# GPIO Export
write_to_file("/sys/class/gpio/export", GPIO_PIN)
time.sleep(1)

# GPIO 방향 설정
write_to_file(f"/sys/class/gpio/gpio{GPIO_PIN}/direction", "out")

# GPIO ON
write_to_file(f"/sys/class/gpio/gpio{GPIO_PIN}/value", "1")
print("LED ON")
time.sleep(2)

# GPIO OFF
write_to_file(f"/sys/class/gpio/gpio{GPIO_PIN}/value", "0")
print("LED OFF")

# GPIO Unexport
write_to_file("/sys/class/gpio/unexport", GPIO_PIN)

3. UART 통신 예제

UART는 외부 장치와 직렬 통신을 수행하는 데 사용됩니다. 다음은 UART를 통해 데이터를 송수신하는 간단한 예제입니다.

3.1 C 언어 기반 UART 통신

#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

int main() {
    int uart_fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY);
    if (uart_fd < 0) {
        perror("Failed to open UART");
        return -1;
    }

    struct termios options;
    tcgetattr(uart_fd, &options);
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    options.c_cflag |= (CLOCAL | CREAD);
    tcsetattr(uart_fd, TCSANOW, &options);

    char send_buf[] = "Hello UART!\n";
    write(uart_fd, send_buf, sizeof(send_buf));

    char recv_buf[100];
    int n = read(uart_fd, recv_buf, sizeof(recv_buf) - 1);
    if (n > 0) {
        recv_buf[n] = '\0';
        printf("Received: %s\n", recv_buf);
    }

    close(uart_fd);
    return 0;
}

3.2 Python 기반 UART 통신

import serial

ser = serial.Serial("/dev/ttyS1", baudrate=115200, timeout=1)
ser.write(b"Hello UART!\n")

response = ser.readline().decode('utf-8')
print(f"Received: {response}")

ser.close()

4. I2C 통신 예제

I2C는 센서와 같은 주변 장치와 통신하는 데 주로 사용됩니다. 다음은 I2C 장치에서 데이터를 읽는 간단한 예제입니다.

4.1 C 언어 기반 I2C 통신

#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <unistd.h>

int main() {
    int file = open("/dev/i2c-1", O_RDWR);
    if (file < 0) {
        perror("Failed to open I2C device");
        return -1;
    }

    int addr = 0x48; // I2C 장치 주소
    if (ioctl(file, I2C_SLAVE, addr) < 0) {
        perror("Failed to set I2C address");
        close(file);
        return -1;
    }

    char reg = 0x00;
    write(file, &reg, 1);

    char data;
    read(file, &data, 1);
    printf("Received data: %d\n", data);

    close(file);
    return 0;
}

4.2 Python 기반 I2C 통신

import smbus

bus = smbus.SMBus(1)
addr = 0x48

# 0x00 레지스터에서 데이터 읽기
bus.write_byte(addr, 0x00)
data = bus.read_byte(addr)

print(f"Received data: {data}")

bus.close()

5. 간단한 웹 서버 구현

RK3399에서 Flask를 사용하여 간단한 웹 서버를 구현할 수 있습니다. 다음은 RESTful API를 제공하는 예제입니다.

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/status", methods=["GET"])
def status():
    return jsonify({"status": "running", "board": "RK3399"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

이 코드를 실행한 후 브라우저에서 http://<보드_IP>:5000/status에 접속하면 상태 정보를 확인할 수 있습니다.


6. 데이터 로깅 애플리케이션

센서 데이터를 주기적으로 읽어 파일에 기록하는 애플리케이션을 작성해보겠습니다.

import time

log_file = "/var/log/sensor_data.log"

while True:
    with open(log_file, "a") as f:
        f.write(f"Timestamp: {time.time()}, Sensor Data: 123\n")
    print("Data logged.")
    time.sleep(10)

7. 결론

이 글에서는 RK3399 기반의 Yocto 환경에서 GPIO, UART, I2C와 같은 주변 장치를 제어하고, 간단한 웹 서버와 데이터 로깅 애플리케이션을 구현하는 방법을 살펴보았습니다. 실무에서도 이러한 기법을 활용하여 다양한 임베디드 애플리케이션을 개발할 수 있습니다.

728x90
반응형