FreeRTOS

FreeRTOS 디버깅 및 문제 해결

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

FreeRTOS를 활용한 프로젝트를 진행하다 보면 디버깅과 문제 해결이 필수적입니다. 이 글에서는 FreeRTOS 디버깅에 필요한 도구와 기법, 주요 문제와 해결 방법을 정리하였습니다. CMSIS v1을 기반으로 디버깅을 진행할 때 특히 유용한 정보를 다룹니다.


디버깅 도구 및 주요 기법

1. 태스크 상태 모니터링

FreeRTOS에서는 태스크의 상태를 모니터링하여 디버깅 정보를 얻을 수 있습니다. 주요 상태는 다음과 같습니다:

  • Running: 현재 CPU에서 실행 중인 태스크.
  • Ready: 실행 대기 상태.
  • Blocked: 이벤트나 시간 대기 중인 상태.
  • Suspended: 실행이 중단된 상태.

예제 코드: 태스크 상태 출력

#include "FreeRTOS.h"
#include "task.h"

void vTaskStatusMonitor(void *pvParameters) {
    TaskStatus_t xTaskDetails;

    while (1) {
        // 특정 태스크의 상태 확인
        vTaskGetInfo(NULL, &xTaskDetails, pdTRUE, eInvalid);
        printf("Task Name: %s, State: %d\n", xTaskDetails.pcTaskName, xTaskDetails.eCurrentState);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

위 코드에서는 vTaskGetInfo API를 사용하여 태스크 상태를 확인합니다.


2. 스택 오버플로우 탐지

FreeRTOS에서 스택 오버플로우는 빈번히 발생하는 문제입니다. 이를 탐지하려면 아래 방법을 활용하세요.

스택 오버플로우 훅 사용

FreeRTOS 설정 파일에서 다음 매크로를 활성화합니다:

#define configCHECK_FOR_STACK_OVERFLOW 2

스택 오버플로우 훅을 구현합니다:

void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    printf("Stack overflow detected in task: %s\n", pcTaskName);
    // 필요 시 시스템을 리셋하거나 로그 저장
}

스택 크기를 조정하고 각 태스크의 스택 사용량을 정기적으로 확인하여 문제를 방지하세요.


3. 디버깅 시 유용한 FreeRTOS API

디버깅을 효과적으로 진행하려면 다음 API를 적극 활용하세요:

  1. uxTaskGetSystemState: 시스템에 등록된 태스크 정보를 한꺼번에 가져옵니다.
  2. vTaskList: 태스크 상태와 스택 여유 정보를 문자열로 출력합니다.
  3. vTaskGetRunTimeStats: 태스크의 실행 시간을 확인합니다.

예제: 시스템 상태 출력

void vPrintTaskList(void) {
    char pcTaskList[512];

    // 태스크 리스트 출력
    vTaskList(pcTaskList);
    printf("Task List:\n%s\n", pcTaskList);
}

흔한 문제와 해결 방법

1. 우선순위 역전

문제 설명

높은 우선순위를 가진 태스크가 낮은 우선순위 태스크에 의해 블로킹되는 현상입니다. 이를 해결하지 않으면 시스템 응답 시간이 비정상적으로 길어질 수 있습니다.

해결 방법

  1. Priority Inheritance: FreeRTOS는 우선순위 상속을 기본적으로 제공합니다. 뮤텍스를 사용하여 보호해야 할 공유 리소스를 감싸십시오.

    SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
    
    void vHighPriorityTask(void *pvParameters) {
        xSemaphoreTake(xMutex, portMAX_DELAY);
        // 보호된 코드
        xSemaphoreGive(xMutex);
    }
  2. 디자인 개선: 태스크 간의 우선순위를 신중히 설계합니다.


2. 태스크 실행 중단

문제 설명

태스크가 예상치 않게 실행되지 않는 경우는 스택 오버플로우, 태스크 삭제, 혹은 시스템 데드락이 원인일 수 있습니다.

해결 방법

  1. 스택 크기 확인: 각 태스크의 스택 크기를 늘려보세요.

  2. 태스크 상태 추적: vTaskGetInfo API를 사용하여 태스크의 상태를 추적합니다.

  3. 타임아웃 설정: 블로킹 API에 적절한 타임아웃을 설정합니다.

    if (xQueueReceive(xQueue, &data, pdMS_TO_TICKS(1000)) == pdFALSE) {
        printf("Queue receive timed out\n");
    }

3. 메모리 부족 문제

문제 설명

시스템의 힙 메모리가 부족하면 새로운 태스크나 큐를 생성할 수 없습니다.

해결 방법

  1. 힙 메모리 크기 조정: FreeRTOSConfig.h에서 configTOTAL_HEAP_SIZE 값을 늘립니다.

    #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16 * 1024 ) )
  2. 메모리 사용 분석: xPortGetFreeHeapSize API를 사용하여 남은 힙 메모리 크기를 주기적으로 확인합니다.

    printf("Free heap size: %d bytes\n", xPortGetFreeHeapSize());
  3. 메모리 재활용 최적화: 동적 메모리 할당 대신 정적 메모리 할당을 고려합니다.

    static StaticTask_t xTaskBuffer;
    static StackType_t xStack[configMINIMAL_STACK_SIZE];
    
    TaskHandle_t xHandle = xTaskCreateStatic(
        vTaskFunction, "TaskName", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, xStack, &xTaskBuffer);

결론

FreeRTOS 디버깅은 시스템 안정성과 성능을 향상시키는 데 핵심적인 과정입니다. 태스크 상태를 모니터링하고 스택 오버플로우를 탐지하며 적절한 API를 활용하여 문제를 해결할 수 있습니다. 흔한 문제들을 사전에 예방하고 체계적으로 해결하면 FreeRTOS 기반의 프로젝트를 더욱 원활하게 운영할 수 있습니다.

반응형