Keil µVision 빌드 오류 해결 — 자주 보는 메시지별 원인과 조치
Keil µVision 은 오류 메시지가 짧고 코드 번호로만 나와서, 처음 보면 무엇을 고쳐야 할지 감이 오지 않습니다. 그런데 실제로 마주치는 오류는 몇 가지로 좁혀지고, 각각 원인이 꽤 정해져 있습니다. 자주 나오는 메시지를 모아 '무엇을 뜻하고 어디를 손대면 되는지' 순서대로 정리했습니다.
오류 메시지 읽는 법
Build Output 창의 메시지는 세 종류로 나뉩니다. 어느 단계에서 멈췄는지 알면 찾아볼 곳이 절반으로 줄어듭니다.
| 접두사 | 단계 | 뜻 |
|---|---|---|
#숫자 (예: #20, #67) | 컴파일 | C 문법·타입 문제. 해당 .c 파일 안에서 해결 |
L6xxx (예: L6218E) | 링크 | 파일은 컴파일됐지만 합치는 단계에서 실패 |
A1xxx | 어셈블 | 어셈블리 파일(.s) 문제. 보통 시작 코드 |
*** error 65 등 | 시뮬레이터·디버거 | 빌드가 아니라 실행/디버그 환경 문제 |
오류가 30개 떴다고 30군데가 잘못된 것이 아닙니다. 첫 번째 오류를 고치고 다시 빌드하면 나머지가 한꺼번에 사라지는 일이 아주 흔합니다. 항상 맨 위부터 보세요.
링크 단계 오류 — 가장 많이 막히는 곳
L6050U — 코드 크기 초과
Error: L6050U: The code size of this image (xxxxx bytes) exceeds the maximum allowed for this version of the linker.무료로 쓰는 MDK-Lite 는 컴파일 결과물이 32KB 를 넘을 수 없습니다. 코드가 틀린 것이 아니라 용량 한도에 걸린 것입니다. 학습용이라면 다음 순서로 줄여 보세요.
- 1Options for Target > C/C++ 에서 최적화를
-O2이상으로 올립니다. 보통 이것만으로 상당히 줄어듭니다. - 2
printf계열을 쓰고 있다면 그 자체로 수 KB 를 먹습니다. 디버그 출력을 UART 직접 전송으로 바꾸거나 MicroLIB 를 켜 보세요 (Options for Target > Target > Use MicroLIB). - 3쓰지 않는 드라이버·라이브러리 파일을 프로젝트에서 제외합니다.
- 4그래도 넘으면 정식 라이선스가 필요합니다. 용량 제한은 설정으로 풀 수 없습니다.
L6218E — Undefined symbol
Error: L6218E: Undefined symbol delay_ms (referred from main.o).main.c 에서 부르는 함수의 **본체를 찾지 못했다**는 뜻입니다. 순서대로 확인하세요.
- 함수를 정의한 .c 파일이 프로젝트 트리에 추가되어 있는지 (헤더만 include 하고 .c 를 안 넣는 실수가 가장 많습니다)
- 함수 이름 철자와 대소문자가 선언과 정의에서 같은지
- C++ 파일에서 C 함수를 부른다면
extern "C"로 감쌌는지 Undefined symbol main이라면 main 함수 자체가 없거나, main.c 가 빌드 대상에서 빠진 것입니다
L6236E — No section matches selector
Error: L6236E: No section matches selector - no section to be FIRST/LAST.시작 코드(startup_xxx.s)가 프로젝트에 없을 때 나옵니다. 칩에 맞는 startup 파일을 추가하거나, Manage Run-Time Environment 에서 Device > Startup 을 체크하세요. 칩 종류를 바꾼 뒤 예전 startup 파일이 남아 있어도 같은 증상이 납니다.
링크 오류는 파일 구성 문제라서 소스 코드를 아무리 들여다봐도 답이 안 나옵니다. Project 창의 파일 목록부터 확인하는 습관을 들이세요.
컴파일 단계 오류
| 메시지 | 원인 | 조치 |
|---|---|---|
error: #5: cannot open source input file "stm32f4xx.h" | 헤더 경로 미등록 | Options for Target > C/C++ > Include Paths 에 헤더 폴더 추가 |
error: #20: identifier "GPIOA" is undefined | 장치 헤더 미포함 또는 디바이스 정의 누락 | 해당 헤더 include 확인, Options > C/C++ > Define 에 칩 매크로(예: STM32F407xx) 추가 |
error: #67: expected a "}" | 괄호·세미콜론 누락 | 오류 줄보다 **그 앞줄**을 먼저 확인 |
warning: #1295-D: Deprecated declaration | 구형 문법 | 동작에는 문제 없음. 함수 선언에 매개변수 타입 명시 |
error: #513: a value of type ... cannot be assigned | 타입 불일치 | 포인터/정수 변환은 명시적 캐스팅 |
헤더를 못 찾는 오류가 반복된다면 경로를 절대경로로 넣지 말고, 프로젝트 폴더 기준 상대경로로 등록하세요. 프로젝트를 다른 PC 로 옮겼을 때 다시 깨지는 일을 막을 수 있습니다.
플래시 다운로드가 안 될 때
No Algorithm found for: 08000000H - 080003FFH
빌드는 성공했는데 보드에 굽는 단계에서 멈춘 경우입니다. 칩에 맞는 플래시 알고리즘이 등록되지 않아서 생깁니다. Options for Target > Debug > Settings > Flash Download 에서 Add 를 눌러 사용하는 칩 계열의 알고리즘을 추가하고, 시작 주소와 크기가 칩 사양과 맞는지 확인하세요.
Flash Download failed - "Cortex-M4"
- 1보드 전원과 디버거(ST-Link/J-Link) 연결을 먼저 확인합니다. USB 케이블이 충전 전용이면 인식되지 않습니다.
- 2Debug > Settings 에서 디버거가 칩을 인식하는지(IDCODE 표시) 봅니다. 인식이 안 되면 배선 문제입니다.
- 3이전에 구운 펌웨어가 디버그 핀을 꺼 버렸을 수 있습니다. Reset 을 누른 채 연결하는 'Connect under Reset' 옵션으로 바꿔 보세요.
- 4그래도 안 되면 ST-Link Utility 나 STM32CubeProgrammer 로 전체 지우기(Full chip erase) 후 다시 시도합니다.
디버거를 여러 개 꽂아 두었거나 다른 프로그램(CubeProgrammer 등)이 포트를 쥐고 있으면 µVision 이 접근하지 못합니다. 다른 프로그램을 먼저 닫아 보세요.
시뮬레이터에서 나는 오류
*** error 65: access violation at 0x40021000 : no 'read' permission실제 보드 없이 시뮬레이터로 돌릴 때 주변장치 레지스터 주소를 읽으면 나오는 메시지입니다. 시뮬레이터가 그 주소를 모른다는 뜻이지 코드가 틀린 것이 아닙니다. 해결은 두 가지입니다.
- Options for Target > Debug 에서 시뮬레이터 대신 실제 디버거를 선택해 보드에서 실행합니다.
- 시뮬레이터를 계속 쓰려면 Debug 창의 Command 란에
MAP 0x40000000, 0x40030000 READ WRITE처럼 해당 영역을 매핑해 줍니다.
GPIO·타이머처럼 주변장치를 건드리는 코드는 시뮬레이터에서 동작을 100% 재현하지 못합니다. 로직 확인까지만 시뮬레이터로 하고, 하드웨어 동작은 보드에서 확인하는 편이 시간을 아낍니다.
그래도 안 될 때 — 5분 점검 순서
- 1Project > Clean Target 후 Rebuild. 예전 오브젝트 파일이 남아 생기는 유령 오류가 사라집니다.
- 2Build Output 의 **첫 번째** 오류만 보고 그것부터 수정.
- 3Project 창에서 필요한 .c 파일이 모두 들어 있는지 확인 (특히 startup 파일).
- 4Options for Target > Device 가 실제 칩과 같은지 확인. 칩을 바꿨다면 Define 매크로도 함께 바꿔야 합니다.
- 5Manage Run-Time Environment 에서 노란색·빨간색 경고가 있는지 확인. 필요한 팩이 빠져 있으면 여기서 드러납니다.
- 6프로젝트 경로에 한글이나 공백이 있으면 옮겨 보세요. 오래된 툴체인에서 경로 문제로 엉뚱한 오류가 납니다.
자주 묻는 질문
Q. 무료판 32KB 제한은 설정으로 풀 수 있나요?
없습니다. MDK-Lite 의 제한은 라이선스 조건이라 최적화나 설정으로 우회할 수 없습니다. 다만 STM32 계열이라면 ST 가 제공하는 무료 툴체인(STM32CubeIDE)에는 용량 제한이 없으므로, 학습 목적이라면 그쪽으로 옮기는 것도 방법입니다.
Q. 빌드는 되는데 보드에서 아무 동작도 하지 않습니다.
대부분 클럭 설정이나 주변장치 클럭 활성화(RCC) 누락입니다. GPIO 를 건드리기 전에 해당 포트의 클럭을 켰는지 먼저 확인하세요. 그다음으로는 실제로 최신 펌웨어가 구워졌는지(다운로드 성공 메시지)와 리셋 여부를 확인합니다.
Q. 오류 줄 번호가 실제 코드와 다릅니다.
헤더에서 발생한 오류가 그 헤더를 include 한 줄로 표시되는 경우입니다. 메시지에 나온 파일 이름을 먼저 보고, 매크로를 많이 쓰는 코드라면 매크로 전개 결과를 의심하세요.
Q. 같은 프로젝트가 다른 PC 에서는 빌드됩니다.
절대경로로 등록된 Include Path 나 설치되지 않은 Device Pack 이 원인일 가능성이 큽니다. Pack Installer 에서 필요한 팩 버전을 맞추고, 경로는 프로젝트 기준 상대경로로 바꾸세요.