28.2.2.2.1. 메모리 제약 환경(예: Pixhawk 1/2)을 위한 특정 Flight Task 빌드 제외 로직

28.2.2.2.1. 메모리 제약 환경(예: Pixhawk 1/2)을 위한 특정 Flight Task 빌드 제외 로직

PX4 펌웨어 프로젝트가 10년이 넘는 세월 동안 생명력을 잃지 않고 오픈소스 항공 생태계를 제패할 수 있었던 가장 강력한 무기 중 하나는, 최신 고성능 컴패니언 컴퓨터뿐만 아니라 고작 1MB의 플래시(Flash) 메모리 변종 칩을 달고 세상에 태어났던 초창기 저가형 구형 보드(Pixhawk 1/2, STM32F427 계열)들까지도 아직까지 현역으로 버리지 않고 끌어안고 가는 미친듯한 ‘하위 호환성(Backward Compatibility)’ 유지 정책 덕분이다.

이를 가능케 하는 마법은 Flight Mode Manager (FMM)의 CMakeLists.txt 빌드 스크립트 파일 가장 밑바닥에 숨겨진, 피도 눈물도 없는 잔혹한 메모리 검열 및 빌드 강제 제외(Exclusion) 매크로 로직이다.

1. STM32 1MB 플래시(Flash) 실리콘 버그와 펌웨어 다이어트의 필요성

초창기 픽스호크 1과 2 보드에 널리 쓰였던 STM32F427 계열 칩 중 초기 생산분(Revision A, Z)에는 하드웨어적으로 매우 치명적인 실리콘 버그가 존재했다. 이론상 2MB의 플래시 메모리를 가지고 태어났어야 할 칩들이지만, 1MB 이상의 후반부 섹터 주소에 코드를 써넣어 접근하려고 하면 칩셋이 하드웨어 적으로 영구 프리징(Lock-up)되어버리는 결함이었다.

PX4 코어 팀은 이 전 세계에 수십만 개가 깔린 1MB 한계치 칩셋들을 휴지통에 버리는 대신, 펌웨어 바이너리(px4_fmu-v2_default.px4)의 빌드 총 뼈대 용량이 어떻게든 절댓값 1MB(약 1024KB) 라인을 넘지 않도록 극한의 다이어트를 감행하는 길을 택했다. 그리고 그 살벌한 칼자루(Pruning)를 쥔 메인 타겟 모듈 중 하나가 바로 덩치가 컸던 FMM의 다종다양한 FlightTask 자식 수학 객체들이었다.

2. CMakeLists.txt 파일 내의 조건부 생존(Survival) 분기문

src/modules/flight_mode_manager/CMakeLists.txt 파일을 해부해보면, 기초적인 수동 조종(ManualPosition)이나 기본적인 웨이포인트 이동(AutoLine) 같은 필수 생존 코어 비행 모드들을 flight_tasks_all 리스트에 담아 먼저 1차적으로 빌드 대상에 올린 다음, 아래와 같이 보드의 스펙 용량을 검열하는 싸늘한 if-else 조건문이 등장한다.

# 보드의 하드웨어 플래시 용량이 넉넉할 때(2MB 이상)에만 추가되는 고급 비행 모드들
if(NOT BOARD_FLASH_SIZE LESS 2000)
    list(APPEND flight_tasks_all
        AutoFollowMe      # 피사체를 화각에 담고 자율 추적하는 촬영용 모드 (용량 높음)
        Failsafe          # 고도화된 3D 비상 회피 및 복귀 알고리즘
        Orbit             # 특정 POI를 중심으로 기수가 안을 향해 원점 비행하는 모드
        VtolTransition    # 틸트로터 등 수직이착륙기의 복잡한 천이 동역학 모드
        ...
    )
endif()

만약 개발자의 터미널이나 CI(Continuous Integration) 서버에서 입력한 타겟 빌드 명령어가 make px4_fmu-v2_default (구형 1MB 보드)라면, CMake 전역 파일(board_config.h 또는 Kconfig)에 세팅된 BOARD_FLASH_SIZE 변수값이 1024로 바인딩 되어 넘어온다.

결과적으로 저 거대한 if(NOT BOARD_FLASH_SIZE LESS 2000) 검문소 조건문이 즉시 거짓(False) 판정을 내리게 되고, 그 블록 안에 속해있던 Orbit 이나 AutoFollowMe 같은 호화스럽고 덩치 큰 고급 수학 제어 모듈 폴더들은 컴파일러 구경도 해보지 못한 채 빌드 대상 리스트에서 영구적으로 탈락(Drop)되어 버린다.

3. 정적 팩토리 메타 코드와의 연동에 의한 완벽한 가지치기

앞선 절에서 보았듯, PX4는 generate_flight_tasks.py 라는 파이썬 매크로가 CMake의 저 flight_tasks_all 리스트 텍스트를 읽어다가 FlightModeManager.cpp 본문의 코드를 대신 꿰매주는 플러그인 생산 방식을 쓴다.

구형 1MB 보드로 빌드 시 애초에 CMake 리스트에서 이름이 잘려 나갔기 때문에, 파이썬 스크립트가 자동 생성해 내는 C++ 팩토리 소스 코드 조각(FlightTasks_generated.cpp) 내부에도 case TASK_ORBIT: return new FlightTaskOrbit(); 같은 객체 메모리 동적 할당 라인이 아예 소스 코드 레벨 텍스트 단위에서부터 증발해버리게 진공 처리된다.

이 무섭도록 우아하고 깔끔한 아키텍처적 연계기 덕분에:

  1. 플래시 롬(ROM) 용량 방어 완료: 1MB 구형 보드의 바이너리 펌웨어 파일은 군더더기 서드파티 고급 모듈들의 찌꺼기를 한 바이트도 포함하지 않은 채 아주 슬림하게 다이어트 성공하여 무사히 1MB 실리콘 한계벽 아래로 칩셋에 플래싱(Flashing)된다.
  2. 런타임 데드락 방어 완료: 컴파일 자체가 되지 않았기 때문에, 구형 보드에 QGroundControl을 물려놓고 조종사가 멋모르고 억지로 화면에서 ‘Orbit(원주 비행)’ 모드를 클릭해 억지 전환을 명령(MAVLink Packet)한다 하더라도, FMM 브로커의 switchTask() 함수 내부에는 생성 호출 매크로 자체가 아예 C++ 컴파일 단계에서 파여 없어져 버렸으므로 널 포인터(nullptr)를 반환하게 된다. FMM은 이를 우아하게 페일세이프(Failsafe)나 기본 Manual 모드로 튕겨내 버림으로써, 공중에서 찾을 수 없는 런타임 메모리 할당 주소를 찾다가 시스템이 드론과 함께 패닉 크래시로 뻗어버리는 최악의 참사를 아키텍처적으로 원천 방어해 낸다.