Troubleshooting — FAQ & 문제 해결¶
XM10 개발 중 자주 발생하는 문제와 해결 방법을 정리한 문서입니다.
빌드 오류¶
경로 길이 문제 (Windows MAX_PATH)¶
증상: 빌드 시 No such file or directory 또는 file name too long 오류 발생
원인: Windows의 기본 경로 길이 제한(260자)을 초과하는 경우 발생합니다. 프로젝트가 깊은 경로에 위치하거나, OneDrive 동기화 폴더 안에 있을 때 빌드 출력 경로가 260자를 초과할 수 있습니다.
해결 방법:
방법 1: 짧은 경로에 SDK 압축 해제 (권장)
본 SDK 는 GitHub Releases 의 ZIP 으로 받습니다. 압축 해제 위치를 드라이브 루트에 가깝게 잡으면 경로 길이 문제를 피할 수 있습니다.
# Releases 페이지에서 본인 Rev ZIP 다운로드 후
Expand-Archive -Path "$HOME\Downloads\Rev2.0.zip" -DestinationPath C:\XM_SDK\ -Force
| 구분 | 경로 예시 | 빌드 최대 경로 |
|---|---|---|
| 권장 | C:\XM_SDK\ |
~130자 |
| 일반 | C:\Users\Name\Documents\GitHub\Extension_Module\ |
~190자 |
| 위험 | C:\Users\...\OneDrive - Company\...\Extension_Module\ |
260자 초과 가능 |
방법 2: Windows Long Path 지원 활성화 (근본 해결)
Windows 10 (1607+) / Windows 11에서 260자 제한을 해제할 수 있습니다.
PowerShell (관리자 권한):
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
또는 그룹 정책:
컴퓨터 구성 > 관리 템플릿 > 시스템 > 파일 시스템 > Win32 긴 경로 사용 → 사용
설정 후 PC 재시작이 필요합니다. 이 설정은 1회만 하면 되며 Git, CMake, GCC 등 모든 도구에 적용됩니다.
한글/공백 경로 오류¶
증상: 빌드 시 No such file or directory 또는 인코딩 관련 오류
원인: 프로젝트 경로 또는 STM32CubeIDE 설치 경로에 한글, 공백, 특수문자가 포함된 경우
해결:
* 프로젝트를 영문 경로로 이동 (예: C:\XM_SDK\)
* STM32CubeIDE를 영문 경로에 설치 (예: C:\dev\STM32CubeIDE)
* Windows 사용자 이름이 한글인 경우: 프로젝트를 사용자 폴더가 아닌 드라이브 루트에 배치
nano.specs 중복 오류¶
증상: fatal error: nano.specs: attempt to rename spec 'link' to already defined spec 'nano_link'
원인: CMake 빌드 설정에서 --specs=nano.specs 플래그가 중복 적용
해결: CMakeLists.txt에서 CMAKE_C_FLAGS와 CMAKE_C_FLAGS_DEBUG/RELEASE가 동일한 플래그를 중복 포함하지 않는지 확인하세요. CMAKE_C_FLAGS에 공통 플래그를 넣고, DEBUG/RELEASE에는 빌드 타입별 플래그만 설정합니다.
redefined 경고 (Rev 1.1 SDK, CMake 빌드)¶
증상: warning: "AGRB_IOIF_FDCAN_ENABLE" redefined 처럼 ..._ENABLE 이름의 값이 다시 정의되었다는 경고 (Rev 1.1 SDK 를 CMake 로 빌드할 때만 나타납니다 — STM32CubeIDE 빌드나 Rev 2.0 SDK 에서는 나타나지 않습니다)
원인: SDK 안에서 같은 설정 값이 두 군데에 정의되어 있어서 나오는 경고입니다.
해결: 동작에는 영향이 없으니 무시해도 됩니다. STM32CubeIDE 로 빌드하면 나타나지 않습니다.
implicit declaration of function 오류 (Rev 2.0 SDK)¶
증상: 빌드가 error: implicit declaration of function '함수 이름' 으로 멈춤 (Rev 2.0 SDK, v2.9.0 이상)
원인: v2.9.0 부터 Rev 2.0 SDK 는 헤더에 선언이 보이지 않는 함수를 부르면 경고가 아니라 오류로 처리합니다. 함수 이름의 오타, 빠진 #include, 헤더에서 없어진 선언이 원인입니다. Rev 1.1 SDK 는 이전과 같습니다.
해결:
1. 그 함수를 선언한 헤더를 #include 합니다. SDK 함수는 보통 #include "xm_api.h" 하나면 됩니다. XM_LOG_* 매크로를 쓰는 .c 파일은 xm_api_logging_raw.h 도 #include 합니다.
2. 함수 이름이 맞는지 API 레퍼런스에서 확인합니다. 이전 버전에서 쓰던 이름이면 v2.9.0 릴리스 노트를 보세요.
3. 직접 만든 함수라면 부르기 전에 원형(prototype)을 선언합니다.
보드 리비전 / SDK ZIP 불일치¶
가운데·우측 버튼이 안 눌리거나, 누르지 않은 버튼이 항상 눌린 것으로 잡힘¶
증상:
- XM_GetButtonEvent(XM_BTN_2) 가 가운데 버튼을 눌러도 반응 없음
- 한 버튼만 동작하고 나머지는 다른 ID 로 잡히거나 stuck (XM_PRESSED 가 고정)
- XM_GetButtonState 와 HAL HAL_GPIO_ReadPin 비교 결과 매핑이 한 칸씩 어긋남
원인: Rev 1.1 보드와 Rev 2.0 보드는 내장 버튼 3 개의 MCU 핀이 다릅니다 — Rev 2.0 으로 가면서 외장 SRAM (PSRAM) 자리를 만들기 위해 버튼 핀이 한 칸 시프트되었습니다.
| BTN 1 (좌) | BTN 2 (중) | BTN 3 (우) | |
|---|---|---|---|
| Rev 1.1 | PC10 | PC11 | PC12 |
| Rev 2.0 | PC11 | PC12 | PC13 |
API 이름 (XM_BTN_1/2/3) 은 양쪽 Rev 에서 좌·중·우 의미를 그대로 유지하지만, 그 안에서 어느 MCU 핀을 읽을지는 SDK 가 본인 Rev 의 main.h 핀 정의를 따라갑니다. 따라서 보드 Rev 와 다른 ZIP 으로 빌드하면 빌드는 통과해도 라이브러리가 잘못된 핀을 읽어 매핑이 어긋납니다.
해결:
1. 보드 라벨에서 Rev 1.1 또는 Rev 2.0 확인. 라벨이 모호하면 외관상 RJ45 Ethernet 포트의 유무로 구별 (Rev 2.0 만 있음). 자세한 비교는 docs/hardware/README.md - 보드 리비전 비교.
2. Releases 에서 본인 Rev 와 같은 ZIP 을 받아 STM32CubeIDE 에 다시 import.
3. 재빌드·플래시 후 Ex.01 (Button & LED Basic) 의 세 버튼 모두 정상 동작 확인.
진단 코드 (선택사항): 본인 보드의 실제 핀을 직접 확인하고 싶다면:
// Run_Loop 안에서 PC10~PC13 을 동시에 읽어 비교
uint8_t pc10 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_10);
uint8_t pc11 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_11);
uint8_t pc12 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_12);
uint8_t pc13 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);
// 좌·중·우 버튼을 한 번씩 눌러 어느 핀이 떨어지는지 확인
// → Rev 1.1 보드면 PC10/11/12, Rev 2.0 보드면 PC11/12/13 이 떨어짐
⚠️ HAL 로 직접 읽는 코드는 진단용입니다. 정상 동작이 확인되면
XM_GetButtonEvent/XM_GetButtonState로 돌아오세요 — 디바운싱과 클릭/롱프레스 인식은 라이브러리가 처리합니다.
Ex.36 (OnDevice Kinesthetic Learning) — Rev 1.1 빌드 실패¶
증상: Rev 1.1 SDK 로 Ex.36 을 빌드하면 link 단계에서 다음 에러가 출력됨(지금 Rev 1.1 SDK 에는 Ex.36 이 들어 있지 않습니다 — 예전 SDK 나 다른 곳에서 가져와 빌드한 경우).
control_task.c:(.text.Active_Entry+0x2a): undefined reference to `XM_UserNV_Read'
control_task.c:(.text.Active_Loop+0x284): undefined reference to `XM_UserNV_Erase'
control_task.c:(.text.Active_Loop+0x292): undefined reference to `XM_UserNV_Write'
collect2.exe: error: ld returned 1 exit status
원인: Ex.36 은 학습된 NN 가중치를 전원 OFF/ON 사이에 보존하기 위해 Internal Flash UserNV API (XM_UserNV_Read/Write/Erase) 를 사용합니다. 이 API 는 Rev 2.0 SDK 의 libXM_Lib.a 에만 포함되어 있고 Rev 1.1 lib 에는 없습니다.
해결:
- 본인 보드가 Rev 2.0 → Rev 2.0 SDK ZIP 으로 다시 import 후 빌드.
- 본인 보드가 Rev 1.1 → Ex.36 은 진행 불가. Ex.35 (MultiLayer_Transparent_Control) 까지 학습한 뒤, Rev 2.0 보드를 확보하면 Ex.36 로 넘어가세요. Ex.36 의 NN + LQR 부분만 보고 싶다면 BTN1 long-press (Flash 저장) 동작을 제거하고 RAM 상에서만 학습/재생하도록 임시 수정해 학습용으로 활용 가능.
본인 보드 Rev 가 헷갈리면 라벨 또는 docs/hardware/README.md - 보드 리비전 비교 의 RJ45 / PSRAM / 버튼 핀 매핑 표로 구분.
USB 연결 문제¶
USB-CDC가 PC에서 인식되지 않음¶
체크리스트:
1. USB-C 케이블이 데이터 전송용인지 확인 (충전 전용 케이블은 불가)
2. Windows 장치 관리자에서 Ports (COM & LPT) 아래에 STMicroelectronics Virtual COM Port 확인
3. 드라이버가 없는 경우: STM32 Virtual COM Port Driver 설치
4. XM10 펌웨어에서 USB CDC 초기화가 정상적으로 완료되었는지 확인
5. (Rev 2.0) USB 메모리가 꽂혀 있으면 PC 와 연결되지 않습니다 — 아래 참고
USB 메모리가 꽂혀 있으면 PC 와 연결되지 않음 (Rev 2.0)¶
🟢 Rev 2.0 전용 — Rev 1.1 에는 USB 메모리 저장이 없습니다.
XM10 의 USB-C 포트는 하나입니다. USB 메모리를 꽂아 두는 동안에는 PC 와 USB 로 연결할 수 없습니다. PhAI Studio · xm10 도구 · USB 로 하는 펌웨어 업로드를 쓸 수 없습니다.
해결: USB 메모리를 뽑고 PC 를 연결하세요. (보드 확인 전)
USB 메모리 저장이 시작되지 않음 (Rev 2.0)¶
🟢 Rev 2.0 전용 — 사용법은 USB 메모리 저장 과 USB 메모리에 저장하기 를 보세요.
체크리스트:
1. USB 메모리가 FAT32 인지 확인 (exFAT · NTFS 는 인식하지 않습니다). 할당 단위는 32 KB 를 권장합니다. 포맷하면 안의 파일이 모두 지워지니 필요한 파일은 먼저 옮기세요.
2. USB 메모리의 빈 공간이 파일을 나누는 크기(기본 10 MB)보다 큰지 확인
3. XM_IsUsbLogReady() 가 true 인지 확인 (Ex.10 · Ex.34 는 LED 1 이 켜집니다)
4. XM_StartUsbDataLog() 가 false 를 돌려주면 XM_GetUsbLogLastStartError() 로 이유 확인 — 시작 실패 이유
5. 시작은 됐는데 곧 끝나면(Ex.10 · Ex.34 는 LED 3 이 켜집니다) XM_GetUsbLogLastStartError() 를 읽어 보세요. 파일을 여는 중에 실패했거나(빈 공간 부족 · 같은 이름의 폴더가 다른 설정), 저장 중에 USB 메모리가 빠졌거나 내부 버퍼가 넘친 경우 등이 있습니다.
6. 폴더 이름이 날짜가 아니거나 이전 저장과 같다면 시계를 맞추지 않아서일 수 있습니다. XM_RTC_SetDateTime() 으로 맞추거나 세션 이름을 직접 정하세요.
디코더 판정이 RE-COLLECT 로 나옴 (Rev 2.0)¶
🟢 Rev 2.0 전용 — 판정 읽는 법은 USB 메모리에 저장하기 에 있습니다.
RE-COLLECT 는 표본이 많이 빠졌거나 공백이 길어서 다시 저장하기를 권한다는 뜻입니다.
해결 순서: 1. USB 메모리를 FAT32(할당 단위 32 KB)로 전체 포맷한 뒤 다시 저장 2. 다른 USB 메모리로 바꿔 보기 3. 저장 주기를 낮추거나 구조체를 줄이기 4. 계속되면 Angel Robotics(엔젤로보틱스) CS팀에 문의
CAN-FD 통신 문제¶
KIT H10과 통신이 안 됨¶
체크리스트: 1. XM10 ↔ KIT H10 케이블이 단단히 연결되었는지 확인 2. KIT H10의 전원이 켜져 있는지 확인 (24V 전원 공급) 3. 커넥터 핀맵 확인: CAN HIGH(5번), CAN LOW(6번)이 올바르게 연결되었는지 검증 4. CAN-FD 보레이트 설정이 일치하는지 확인
센서 허브 모듈 연동 오류¶
체크리스트: 1. 센서 허브 모듈의 전원과 CAN-FD 케이블이 제대로 연결되었는지 확인 2. 센서 허브가 XM10 에 자동으로 인식(연결)되는지 확인 3. 센서 허브 모듈의 펌웨어 버전이 XM10 SDK와 호환되는지 확인
IMU Hub·EMG Hub 는 내부에서 개발 중인 모듈입니다. 사용하려면 https://huphailab.com/contact 로 문의해 주세요.
디버깅 관련¶
ST-Link 연결 실패¶
체크리스트:
1. ST-Link 디버거의 USB 연결 상태 확인
2. SWD 4핀 케이블의 핀 배치가 올바른지 확인 (SWDIO, SWCLK, GND, 3.3V)
3. STM32CubeIDE의 Debug Configuration에서 ST-Link가 감지되는지 확인
4. ST-Link Firmware를 최신 버전으로 업데이트 (Help > ST-Link Upgrade)
디버깅 시 변수 값이 Optimized Out¶
원인: Release 빌드 설정(-O2)에서 컴파일러 최적화로 변수가 제거됨
해결: Debug 빌드 설정(-Og -g3)으로 빌드하세요. Project > Properties > C/C++ Build > Settings > Optimization 에서 확인할 수 있습니다.
디버그 시작 시 main() 에서 멈춤 / Break at address "0x800xxxx" with no debug information 팝업¶
정상 동작입니다 — 버그가 아닙니다. XM10 은 부트로더(AGR_BOOT)와 앱 펌웨어가 하나의 칩에 두 개의 독립 이미지로 올라가는 구조라, 디버거에서 다음 두 가지가 보일 수 있습니다.
Thread #1 suspended: breakpoint main()로 멈춤 — STM32CubeIDE 기본 설정Set breakpoint at: main때문입니다(모든 CubeIDE 프로젝트 공통).Resume(F8) 를 누르면 실행됩니다. 매번 멈추는 게 싫으면Debug Configuration > Startup탭에서Set breakpoint at: main체크를 해제하세요.Break at address "0x0800xxxx" with no debug information available, or outside of program code—0x0800xxxx(예:0x0800bf14)는0x08040000(앱 시작) 아래 = 부트로더 영역입니다. 부트로더는 앱과 별개 바이너리라 앱 프로젝트에 디버그 심볼이 없으므로, 디버거가 "심볼 없음"을 정확히 알리는 것뿐입니다.Resume(F8) 로 진행하면 됩니다.
참고: 디버그 중 리셋(Restart 버튼의 Software system reset / Hardware reset)을 누르면 CPU 가 실제 부트로더부터 다시 실행하므로 위 2번이 더 자주 보일 수 있습니다. 이게 거슬리면
Debug Configuration > Startup > Reset Behaviour를 Core reset 또는 None 으로 바꿔보세요. (벡터 테이블 미설정으로 signal handler 에 빠지는 것과는 다른, 정상 정지입니다 — 부트로더 디버그 설정 참고.)
자주 마주치는 함정¶
코드 작성 패턴¶
sprintf("%.2f", val) 결과가 정수처럼 출력됨¶
원인: newlib-nano (기본 ARM 라이브러리) 가 float 형식 미지원
해결: STM32CubeIDE → Project > Properties > C/C++ Build > Settings > MCU Settings → "Use float with printf" 체크.
static 누락으로 변수가 매 호출 0 으로 초기화¶
증상: 토글 동작이 안 되거나, 타이머가 매번 reset
원인: 함수 내부 변수는 매 호출 스택에 새로 생성. static 키워드로 보존 필요.
// ❌ 잘못된 예
static void Run_Loop(void) {
bool toggle = false; // 매 호출 false 로 reset
if (clicked) toggle = !toggle; // 절대 true 가 안 됨
}
// ✅ 올바른 예
static void Run_Loop(void) {
static bool toggle = false; // 다음 호출까지 유지
if (clicked) toggle = !toggle;
}
XM_TSM_Run() 누락으로 상태 콜백 미실행¶
증상: Add_State 등록했는데 on_loop 함수가 호출 안 됨
해결: Control_Loop() 안에서 반드시 XM_TSM_Run(handle); 호출.
Active Low vs Active High 혼동¶
증상: 외부 스위치 누름인데 LED 가 반대 동작
규칙:
- 풀업 (INPUT_PULLUP) + 스위치 한쪽 GND → 눌림 = XM_LOW (Active Low)
- 풀다운 (INPUT_PULLDOWN) + 스위치 한쪽 3.3V → 눌림 = XM_HIGH (Active High)
본 SDK 의 내장 버튼 (XM_GetButtonState) 은 추상화되어 항상 XM_PRESSED.
Edge Detection 누락¶
증상: 버튼 한 번 눌렀는데 토글이 여러 번 발생
해결: 직전 상태 (s_btn_prev) 와 현재 상태 비교로 "방금 막 눌린 순간" 만 감지.
bool btn_now = (XM_DigitalRead(BTN) == XM_LOW);
bool pressed = (btn_now && !s_btn_prev); // Leading edge
s_btn_prev = btn_now;
if (pressed) { /* 1회만 실행 */ }
또는 XM_GetButtonEvent() 의 read-clear 동작 활용 (Ex.02 참조).
USB / 통신 함정¶
USB-CDC 텍스트 메시지가 터미널에 안 보임¶
XM_SendUsbDebugMessage 로 보낸 텍스트는 일반 시리얼 터미널에서 읽는 용도입니다.
원인 1: 다른 PC 프로그램이 동일 COM 포트 점유 (PhAI Studio · xm10 도구 · 다른 터미널 — PC 프로그램은 한 번에 하나만 연결하세요)
원인 2: USB-C 케이블이 데이터 전송 불가 (충전 전용)
원인 3: Windows 장치 관리자에서 STMicroelectronics Virtual COM Port 미인식
원인 4 (Rev 2.0): USB 메모리가 꽂혀 있음 — 꽂혀 있는 동안에는 PC 와 USB 로 연결되지 않습니다 (설명)
해결 순서: 1. 모든 시리얼 클라이언트 종료 → 하나만 단독 실행 2. 데이터 전송 가능 USB-C 케이블 (가능하면 PC 후면 USB-A 직결, 허브 X) 3. STM32 VCP 드라이버 설치 4. (Rev 2.0) USB 메모리가 꽂혀 있으면 뽑고 PC 를 연결합니다 (설명). (보드 확인 전)
KIT H10 / 로봇 제어 함정¶
XM.status.h10.* 가 모두 0¶
- KIT H10 본체 전원 OFF → 24 V 입력 확인
- CAN-FD HIGH/LOW 핀 거꾸로 → 핀맵 (01-hardware-setup.md Figure 1) 확인
- KIT H10 FW v2.3.0 미만 → kit-h10-firmware/ 가이드
forwardVelocity, footContact 등 보행 분석 데이터가 항상 0¶
원인: Body Data 전제조건 미충족 — XM_SendUserBodyData() 미호출
해결: examples/README.md — Body Data 안내 참조.
SetAssistTorque 호출했는데 H10 안 움직임¶
XM_SetControlMode(XM_CTRL_CONTROL)누락 → Active 진입 시 1회 호출- 안전 스위치 트리거 상태 → ERROR 상태 점검
- H10 본체 모터 활성화 안 됨 → 본체 LED / 토크 큐 확인
환경 / 시스템 함정¶
Windows 사용자명에 한글 포함¶
증상: C:\Users\홍길동\... 경로에서 빌드 시 한글 인코딩 또는 MAX_PATH 문제
해결: 사용자 폴더 대신 드라이브 루트 에 SDK 압축 해제:
클라우드 동기화 폴더 (OneDrive, iCloud) 에 압축 해제¶
증상: 빌드 중 파일 잠금 충돌, 동기화 충돌 파일 생성
해결: 클라우드 비동기 폴더 (예: C:\dev\) 로 이동.
문제가 해결되지 않으면 GitHub Issues에 문의해주세요.
🤖 Claude Code 사용자:
"Ex.XX 가 안 돼"또는"빌드 에러 났어"한 줄로example-helper스킬이 본 페이지의 해당 항목 + 예제 README 의 ⚠️ 섹션을 인용해 답합니다.