Embedded / IoT
Intermediate
ESP-IDF / Arduino ESP32 Core
ESP32 FreeRTOS 듀얼 코어 분산 태스크 및 스레드 세이프 큐(Queue) 통신
Core 0(Wi-Fi/센서 수집)과 Core 1(UI 렌더링/모터 제어)에 독립 태스크를 고정(PinToCore)하고 FreeRTOS Queue를 통해 락 없이 데이터를 교환하는 패턴.
#Embedded #ESP32 #FreeRTOS #DualCore #Multithreading
핵심 개념ESP32는 2개의 Xtensa 32비트 LX6 코어를 탑재하고 있습니다. 단일 루프에서 Wi-Fi 패킷 통신과 고속 센서 읽기, 디스플레이 화면 갱신을 동시에 돌리면 프레임 드랍이 발생합니다. Core 0에 통신 태스크를, Core 1에 렌더링 태스크를 할당하고 Queue로 결합합니다.
1. FreeRTOS 듀얼코어 태스크 스케줄링 C++ 코드
#include <Arduino.h>
struct SensorData {
int id;
float value;
};
QueueHandle_t dataQueue;
void SensorTask(void *pvParameters) {
SensorData data;
while (1) {
data.id = 1;
data.value = analogRead(34) * (3.3f / 4095.0f);
// 큐에 데이터 전송 (대기시간 10ms)
xQueueSend(dataQueue, &data, pdMS_TO_TICKS(10));
vTaskDelay(pdMS_TO_TICKS(50)); // 20Hz 수집 주기
}
}
void DisplayTask(void *pvParameters) {
SensorData receivedData;
while (1) {
if (xQueueReceive(dataQueue, &receivedData, portMAX_DELAY)) {
Serial.printf("[Core %d] Sensor %d: %.2f V\n",
xPortGetCoreID(), receivedData.id, receivedData.value);
}
}
}
void setup() {
Serial.begin(115200);
dataQueue = xQueueCreate(10, sizeof(SensorData));
// Core 0에 센서 수집 태스크 고정
xTaskCreatePinnedToCore(SensorTask, "SensorTask", 4096, NULL, 1, NULL, 0);
// Core 1에 디스플레이/로직 태스크 고정
xTaskCreatePinnedToCore(DisplayTask, "DisplayTask", 4096, NULL, 1, NULL, 1);
}
void loop() {
vTaskDelete(NULL); // 기본 loop 태스크 제거
}