# ============================================================================= # arm-none-eabi-toolchain.cmake - STM32F407VGT6 (Cortex-M4F) 크로스 컴파일 툴체인 # # 사용: # cmake -S firmware -B firmware/build -G Ninja \ # -DCMAKE_TOOLCHAIN_FILE=firmware/cmake/arm-none-eabi-toolchain.cmake # # 대상: Cortex-M4F, 하드웨어 단정밀도 FPU(FPv4-SP-D16), Thumb. # 폐쇄망(air-gapped): newlib-nano + nosys stub 으로 자급식 바이너리 생성. # - 외부 런타임/네트워크 의존 없음(빌드 산출물 자체 완결). # ============================================================================= # ── 베어메탈/RTOS 타깃: OS 없음 → Generic ──────────────────────────────────── set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR arm) # CMake 가 호스트 라이브러리/헤더를 찾지 않도록(크로스 빌드 격리). set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # ── 툴 위치 탐색 ───────────────────────────────────────────────────────────── # PATH 에서 arm-none-eabi-* 를 찾는다. 다른 경로면 -DTOOLCHAIN_PREFIX 로 지정. # 예) -DTOOLCHAIN_PREFIX="C:/Program Files (x86)/Arm/.../bin/arm-none-eabi-" if(NOT DEFINED TOOLCHAIN_PREFIX) set(TOOLCHAIN_PREFIX "arm-none-eabi-") endif() # Windows 실행파일 확장자(.exe) 처리: PATH 탐색 시 자동 인식되지만 명시 경로 대비. if(WIN32) set(TC_EXT ".exe") else() set(TC_EXT "") endif() set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc${TC_EXT}") set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++${TC_EXT}") set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc${TC_EXT}") set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy${TC_EXT}" CACHE FILEPATH "objcopy") set(CMAKE_OBJDUMP "${TOOLCHAIN_PREFIX}objdump${TC_EXT}" CACHE FILEPATH "objdump") set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size${TC_EXT}" CACHE FILEPATH "size") set(CMAKE_AR "${TOOLCHAIN_PREFIX}ar${TC_EXT}" CACHE FILEPATH "ar") # ── try_compile: 실행파일이 아닌 정적 라이브러리로 검증 ────────────────────── # 베어메탈 타깃은 링커 스크립트/startup 없이 실행파일을 만들 수 없으므로 # CMake 의 컴파일러 식별 단계에서 STATIC_LIBRARY 를 사용한다. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # ── CPU/FPU 아키텍처 플래그 (C / C++ / ASM / LINK 공통) ────────────────────── set(CPU_FLAGS "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16") # 함수/데이터 섹션 분리 → 링크 시 미사용 섹션 제거(--gc-sections)로 크기 최소화. set(OPT_FLAGS "-ffunction-sections -fdata-sections") # 공통 컴파일 플래그(언어 무관). CMAKE__FLAGS_INIT 은 캐시 채우기 전 1회 적용. set(CMAKE_C_FLAGS_INIT "${CPU_FLAGS} ${OPT_FLAGS}") set(CMAKE_CXX_FLAGS_INIT "${CPU_FLAGS} ${OPT_FLAGS} -fno-exceptions -fno-rtti") set(CMAKE_ASM_FLAGS_INIT "${CPU_FLAGS} -x assembler-with-cpp") # ── 링크 플래그 ────────────────────────────────────────────────────────────── # newlib-nano(--specs=nano.specs): 작은 libc. # nosys(--specs=nosys.specs): _read/_write/_sbrk 등 시스템콜을 빈 stub 로 제공 # → 폐쇄망/베어메탈에서 OS 없이 링크 성립. (printf 의 retarget 은 applog/UART 측에서.) # --gc-sections: 미사용 코드 제거. -Map: 메모리 맵 산출(크기 분석/디버깅). # -u _printf_float: newlib-nano 의 vsnprintf/printf 가 %f 를 처리하도록 부동소수 # 포맷 코어를 강제 링크한다(약 +7KB flash, 1MB 중 무시할 수준). app_sht30.c 등 # 진단 로그가 온습도를 %.2f 로 출력하므로 필요하다. (서버로 보내는 본문은 # jb_fixed2() 로 printf 없이 만들므로 wire 계약과는 무관하다.) set(CMAKE_EXE_LINKER_FLAGS_INIT "${CPU_FLAGS} --specs=nano.specs --specs=nosys.specs \ -u _printf_float \ -Wl,--gc-sections \ -Wl,--print-memory-usage \ -Wl,--no-warn-rwx-segments")