Firmware & RTOS/FreeRTOS & Real-time Scheduling

FreeRTOS IoT 프로젝트: STM32 기반 온습도 모니터링 시스템 구현 가이드

임베디드 친구 2025. 1. 18. 10:10
반응형

임베디드 시스템에서 여러 작업을 동시에 처리해야 하는 IoT 기기 개발 시, RTOS는 선택이 아닌 필수입니다. 이번 포스팅에서는 STM32와 FreeRTOS(CMSIS-RTOS v2)를 활용하여 온습도 데이터를 수집하고, OLED 출력 및 UART 전송을 동시에 수행하는 실전 프로젝트를 구현해 보겠습니다.

Generated by Gemini AI.


1. 프로젝트 설계: 다중 태스크 및 자원 관리

효율적인 시스템을 위해 기능을 세 개의 독립적인 태스크로 분리하고, 태스크 간 데이터 전달을 위해 큐(Queue)를, 디스플레이 자원 보호를 위해 뮤텍스(Mutex)를 사용합니다.

주요 태스크 정의

  1. Sensor Task (우선순위: 높음): BME280 센서에서 1초마다 데이터를 읽어 큐에 전달합니다.
  2. Display Task (우선순위: 보통): 큐에서 데이터를 받아 OLED에 실시간 수치를 출력합니다.
  3. Communication Task (우선순위: 보통): 큐에서 데이터를 받아 UART로 PC에 전송합니다.

주의: 하나의 큐를 두 태스크(Display, Comm)가 동시에 Get하면 데이터가 한쪽으로만 흘러갑니다. 이를 방지하기 위해 각 태스크 전용 큐를 만들거나, 데이터를 복사해서 전달하는 구조가 안전합니다. 본 예제에서는 가독성을 위해 구조체 포인터 공유 방식을 기준으로 설명합니다.


2. 핵심 코드 구현 (CMSIS-RTOS v2 기준)

2.1 초기화 및 구조체 정의

C
 
#include "cmsis_os2.h"
#include "ssd1306.h"

typedef struct {
    float temperature;
    float humidity;
} SensorData_t;

osMessageQueueId_t sensorQueue;
osMutexId_t displayMutex;

// 큐 및 뮤텍스 생성
sensorQueue = osMessageQueueNew(5, sizeof(SensorData_t), NULL);
displayMutex = osMutexNew(NULL);

2.2 센서 데이터 수집 태스크

C
 
void SensorTask(void *argument) {
    SensorData_t data;
    for (;;) {
        data.temperature = BME280_ReadTemperature();
        data.humidity = BME280_ReadHumidity();

        // 큐로 데이터 전송 (Timeout 0으로 비차단 전송)
        osMessageQueuePut(sensorQueue, &data, 0, 0);
        
        osDelay(1000); // 1초 대기
    }
}

2.3 OLED 디스력 및 자원 보호

여러 태스크가 I2C 버스를 공유할 때 발생할 수 있는 데이터 충돌을 뮤텍스로 방지합니다.

C
 
void DisplayTask(void *argument) {
    SensorData_t receivedData;
    char str[20];

    for (;;) {
        if (osMessageQueueGet(sensorQueue, &receivedData, NULL, osWaitForever) == osOK) {
            // 뮤텍스 획득: I2C 디스플레이 자원 점유
            if (osMutexAcquire(displayMutex, osWaitForever) == osOK) {
                sprintf(str, "T: %.1fC", receivedData.temperature);
                SSD1306_GotoXY(0, 0);
                SSD1306_Puts(str, &Font_11x18, 1);
                SSD1306_UpdateScreen();
                
                osMutexRelease(displayMutex); // 뮤텍스 반환
            }
        }
    }
}

3. 시스템 최적화 포인트 (수익화 및 기술 전문성)

구글 검색 상위 노출을 위해 임베디드 개발자가 놓치기 쉬운 최적화 팁을 추가합니다.

  1. 스택 크기 최적화: printf나 sprintf는 스택을 많이 소모합니다. vTaskList를 활용해 각 태스크의 스택 여유 공간을 확인하고 최적의 크기를 할당하세요.
  2. 우선순위 상속(Priority Inheritance): 뮤텍스를 사용하면 낮은 우선순위 태스크가 리소스를 잡고 있을 때 높은 우선순위 태스크가 밀리는 현상을 방지할 수 있습니다.
  3. Tickless Idle 활성화: 배터리 기반 IoT 기기라면 configUSE_TICKLESS_IDLE을 활성화하여 전력 소비를 극적으로 줄여야 합니다.

결론

이번 프로젝트를 통해 FreeRTOS의 핵심 요소인 Task, Queue, Mutex를 실무에 어떻게 적용하는지 살펴보았습니다. RTOS를 활용하면 복잡한 IoT 로직을 구조화된 코드로 관리할 수 있으며, 시스템의 안정성을 크게 높일 수 있습니다.


포스팅이 도움이 되셨다면 공감과 댓글 부탁드립니다! STM32와 FreeRTOS 관련 궁금한 점은 언제든 질문해 주세요.

반응형