| 编辑推荐: |
本文介绍了Keil命令行工具,主要命令行工具以及主流的方式来使用这些命令行工具,希望能为大家提供一些参考或帮助。
文章来自于微信公众号嵌入式电子学习,由火龙果Alice编辑推荐。 |
|
Keil命令行工具:armcc、armlink、fromelf
1. Keil命令行概述
Keil 的命令行工具本质上是将其图形界面(µVision)的功能剥离出来,通过一系列可执行程序、命令和参数来实现项目的编译、链接、格式转换等操作。Keil提供了完整的命令行工具链,支持在不启动IDE的情况下完成项目的编译、链接和生成固件。这对于批量构建和自动化测试至关重要。例如,在cmd窗口调用 UV4.exe 程序对指定路径下的keil工程进行编译:
|
D:\Keil_v5\UV4\UV4.exe -b -j0 -o build.log E:\TestKeil\TestDemo\Template.uvprojx
|
会自动将编译后的文件比如.o文件、hex文件、map文件等等存放到工程目录下的 Obj 文件夹下,这个和Keil工程内部的配置有关,本质和手动打开Keil工程进行编译没有区别。
2. 主要命令行工具
Keil 的工具链主要由以下几个核心组件构成,它们通常位于 Keil 安装目录下的 Keil_v5/ARM/ARMCLANG/bin 或 Keil_v5/ARM/ARMCC/bin 以及 Keil_v5/UV4 等路径中。以下测试以Keil工程目录为例:
2.1 μVision可执行程序 (UV4.exe)
μVision IDE本身也支持命令行操作。
基本命令格式
|
UV4.exe [options] project_file.uvprojx
|
2.1.1 主要参数
| 参数 | 说明 |
| -b |
批量构建编译模式(无GUI) |
| -j0 |
启用多核编译(job数量,0=自动检测) |
| -o <file> |
输出日志到指定文件即命名文件 |
| -r <target> |
重建指定目标 |
| -t <target> |
切换活动目标 |
| -s |
静默模式 |
2.1.2 应用示例
|
REM 基础构建 REM 需要将路径添加到环境变量里才能直接使用exe
UV4.exe -b MyProject.uvprojx
REM 多核编译+日志输出 UV4.exe -b -j0 -o build.log MyProject.uvprojx
REM 重建特定目标 UV4.exe -b -r Target Target1 MyProject.uvprojx
|
|
set pathF=D:\Keil_v5\UV4\UV4.exe
set PROJECT=Template.uvprojx
"%pathF%" -b -j0 "%PROJECT%" -o build.log
|
然后就会在Obj文件夹生成.o文件、hex文件等等,和直接打开Keil工程进行编译的效果完全一样,所用的配置就是Keil工程里的配置,比如指定生成的文件存放路径是Obj文件夹下、生成调试信息文件等等。并且还会生成日志文件build.log
2.2 ARM编译器 (armcc/armclang)
作用 : 将 C/C++ 源代码编译成目标文件。
armcc (传统编译器)
|
armcc [options] source_files [output_dir]
|
armclang (LLVM-based)
|
armclang [options] source_files [output_dir]
|
2.2.1 编译参数
目标架构相关
|
--cpu=Cortex-M3 : 指定代码对应CPU内核是M3 --thumb : 指示编译器生成 Thumb 指令集代码 --arch=armv7-m : 指示对应的是armv7架构 --float-abi=hard : 带有硬件浮点 --fpu=fpv4-sp-d16 : FPU类型
|
优化控制
|
-O<level>: 优化级别,如 `-O0` (无优化)
-O0 : 无优化(调试时常选) -O1 : 轻度优化 -O2 : 中度优化 -O3 : 完全优化即最高速度优化 -Os : 尺寸优化 -Otime : 速度优先
|
调试信息
|
-g : 生成调试信息 --dwarf_version=number : DWARF版本
|
预处理和输出
-E : 仅预处理
-c : 只编译不链接,生成对象文件 (.o)
-o <file># 输出文件
-I<path> : 指定头文件搜索路径,必须包含项目中的所有 #include 路径
-D<macro>[=value] : 定义预处理器宏,相当于代码中的 #define
|
2.2.2 应用示例
|
REM STM32F103编译示例
armcc --cpu=Cortex-M3 --thumb --fpu=none -I.\Inc -I.\Drivers\CMSIS\Include -D STM32F103x_MD -D USE_STDPERIPH_DRIVER -O1 -g -c main.c -o obj\main.o
|
上述例子是只编译main.c源文件,运行后会在Obj文件下生成main.o文件。
固定格式就是显示待编译文件,然后是输出文件所在路径以及输出文件名称。
2.3 汇编器 (armasm)
作用 : 将汇编源代码 (.s) 编译成目标文件。
|
armasm [options] source_file.s
|
2.3.1 主要参数
|
--cpu=Cortex-M3 : 指定目标 CPU 内核 --apcs=interwork : AAPCS标准 -g : 生成调试信息 -I<path> : 指定包含文件路径即类似于头文件 --pd "<define> SETA <val>" : 在汇编时定义符号,类似于 C 中的 `-D`宏定义 -o <file> : 输出文件
|
2.3.2 应用实例
|
REM 汇编startup文件 armasm --cpu=Cortex-M3 --apcs=interwork ^ -I.\Libraries\CMSIS ^ --pd "STM32F103xx SETA 1" ^ .\Libraries\CMSIS\startup_stm32f103x_hd.s -o Obj\startup.o
|
上述是对starup_stmf103x_hd.s这一个文件进行编译,运行后会在Obj文件夹生成汇编文件编译后的.o文件即startup.o
2.4 链接器 (armlink)
作用 : 将一个或多个目标文件 (.o) 和库文件 (.a, .lib) 组合在一起,根据分散加载文件分配内存地址,生成最终的 ELF/ DWARF 格式的可执行文件 (.axf, .elf)。
|
armlink [options] object_files
|
2.4.1 主要参数
基础控制
|
--scatter=<file> : 指定分散加载描述文件 (.sct),该文件定义了内存布局(ROM, RAM, 栈,堆的位置)
--map : 生成内存映射文件 (.map),其中详细 列出了各段、函数、变量的地址和大小,对分析 内存使用情况必不可少
--list=<file> : 指定生成的 .map 文件名
--output=<file> : 指定编译后输出文件的名称
--entry=<address> : 入口点
|
库相关
|
--userlibpath=<paths> : 指定要链接的用户库路径 --keep=<symbol> : 强制保留符号 --library=<lib> : 指定要链接的库文件
|
调试和分析
|
--callgraph : 调用图分析
--info=sizes,totals : 输出特定信息,例如 `-- info=totals` 显示总读写数据大小, `--info=unused` 列出未使用的段
--symdefs=<file> : 生成一个全局符号定义文件, 可用于后续的增量链接或其他模块的引用
|
2.4.2 链接示例
REM STM32链接示例,实际上armlink并不能识别和展开*.o!!!!,需要额外处理
|
REM STM32链接示例,实际上armlink并不能识别和展开*.o!!!!,需要额外处理 armlink --scatter="STM32F103VE.sct" --map --list="build\Map.map" --output="build\application.axf" --entry=Reset_Handler --info=sizes,totals,unused obj\*.o
|
上述是对Obj文件夹里所有的.o文件进行链接处理,链接后会在Obj文件夹下生成axf文件和map文件。
2.5 fromelf格式转换工具
|
fromelf [options] input_file
|
2.5.1 功能参数
|
--bin : 生成纯二进制文件 (.bin),最常用的烧录格式
--i32 : 生成 Intel HEX 文件 (.hex),另一种常见的烧录格式
--m32 : 生成 Motorola S-Record 文件 (.srec) --output=<file># 指定将输出文件存放到 输出目录或文件
-c : 文本反汇编 -s : 打印符号表 -t : 打印字符串表 --text -c : 反汇编代码段,生成可读的汇编列表文 件,常用于分析或调试
|
2.5.2 实用案例
|
REM 生成多种格式固件 fromelf --bin --output="firmware.bin" application.axf
fromelf --i32 --output="firmware.hex" application.axf
fromelf -c application.axf > disassembly.txt
|
上述是将axf文件转成bin文件和hex文件,并且测试了批处理参数放在不同位置的效果,结果是一样的。运行后会在Obj文件夹下生成bin和hex。
2.6 armar库管理工具
作用 : 将多个目标文件打包成一个静态库文件 (.a、.lib),方便代码复用和管理。
|
-r <archivearchive> <objects...>: 替换或向库中添加新的目标文件。 -d <archive> <objects...>: 从库中删除指定的目标文件。 -t <archive>: 列出库中包含的所有目标文件。
|
3.实际使用
有两种主流的方式来使用这些命令行工具:
1. 手动调用工具链 :完全用户控制,灵活性高,但配置复杂。
2. 使用 µVision 命令行模式 :利用已有的 µVision 项目文件,通过µVision 驱动工具链,简单可靠。
3.1 方法一:手动调用工具链
这种方法需要写一个批处理脚本。
基本流程
1. 编译所有 .c 文件
例如编译main.c文件
|
armcc --cpu=Cortex-M3 -I.\Libraries\CMSIS -I.\User ^ -I.\APP\led -I.\Public -I.\Libraries\STM32F10x_StdPeriph_Driver\inc ^ -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER -O1 -g -c ".\User\main.c" -o ".\Obj\main.o"
|
2. 汇编所有 .s 文件
例如编译startup_stm32f10x_hd.s文件
|
armasm --cpu=Cortex-M3 --apcs=interwork ^ -I.\Libraries\CMSIS ^ --pd "STM32F103xx SETA 1" ^ .\Libraries\CMSIS\startup_stm32f10x_hd.s -o .\Obj\startup.o
|
3. 链接所有 .o 文件
|
setlocal enabledelayedexpansion set OBJ_FILES= for %%f in (.\Obj\*.o) do ( set OBJ_FILES=!OBJ_FILES! "%%f" )
armlink --scatter=".\Obj\Template.sct" ^ --map --list=".\Obj\Template.map" ^ --output=".\Obj\Template.axf" ^ --entry=Reset_Handler ^ --info=sizes,totals,unused ^ %OBJ_FILES%
|
4. 生成最终烧录文件
|
fromelf --bin Template.axf --output Template.bin fromelf --i32 Template.axf --output Template.hex
|
3.2 方法二:使用 µVision 命令行模式
这是最常见和最不容易出错的方式,因为直接复用了在 µVision IDE 中配置好的所有配置。
命令 : <KeilPath>/UV4/UV4.exe
3.2.1 主要参数
|
-b <project_file.uvprojx>: 执行批处理构建。 这是最常用的参数。
-j0: 启用多线程编译,0 表示使用与 CPU 核心 数相同的线程,大幅提升构建速度。
-o <logfile>: 将构建输出重定向到一个日志 文件中。
|
3.2.2 应用示例
1. 基础构建
|
"D:\Keil_v5\UV4\UV4.exe" -b "MyProject.uvprojx" -j0
|
这条命令会在当前BTA批处理文件所在目录下寻找 MyProject.uvprojx 项目文件,并使用所有CPU核心对其进行编译。如果两者不在同一目录下,则需要指定 uvprojx 的路径
2. 构建并记录日志
|
"D:\Keil_v5\UV4\UV4.exe" -b "MyProject.uvprojx" -j0 -o build_log.txt
|
在当前目录下生成日志文件 build_log.txt 来判断构建是否成功。
|
echo Starting Build... set WORKSPACE=E:\TestKeil\TestDemo
"D:\Keil_v5\UV4\UV4.exe" -b "%WORKSPACE%\MyProject.uvprojx" -j0 -o build_log.txt
if %ERRORLEVEL% == 0 ( echo Build Succeeded! exit 0 ) else ( echo Build Failed! exit 1 )
|
4.综合例子
这个会不同于Keil工程的目录架构,这个可以将所有的 .c 源文件放到同一个 src 文件夹下,然后将所有 .h 头文件放到同一个 inc 文件夹下,然后将分散加载文件 .sct 放到 sct 文件夹下,然后建立一个 obj 文件夹用于存放编译生成的 .o 文件,建立一个 build 文件夹用于存放最后生成的 bin、hex、axf、map 文件。最后可以将下面的批处理文件放到这些同级目录下。

|
@echo off setlocal enabledelayedexpansion
REM 1、设置工具链路径 set KEIL_PATH=D:\Keil_v5\ARM\ARMCC\bin set ARMCC_PATH=%KEIL_PATH%\armcc.exe set ARMASM_PATH=%KEIL_PATH%\armasm.exe set ARMLINK_PATH=%KEIL_PATH%\armlink.exe set fromelf=%KEIL_PATH%\fromelf.exe echo %ARMCC_PATH%,%ARMASM_PATH%,%ARMLINK_PATH%,%fromelf% pause
REM 2、项目配置 set PROJECT_NAME=Template set TARGET_CPU=Cortex-M3 set SOURCE_DIR=src set OBJ_DIR=obj set OUTPUT_DIR=build set SCATTER_FILE=.\sct\Template.sct
REM 3、创建目录 if not exist "%OBJ_DIR%" mkdir "%OBJ_DIR%" if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
REM 4、公共编译选项 set COMMON_FLAGS=--cpu=%TARGET_CPU% --thumb --fpu=none set INCLUDES=-I".\inc" set DEFINES=-D STM32F10X_MD -D USE_STDPERIPH_DRIVER set OPTIONS=-O1 -g -c
echo ============================================================================== echo Starting Build Process for %PROJECT_NAME% echo ======================================== pause
REM 5、编译C源文件 for %%f in (%SOURCE_DIR%\*.c) do ( echo Compiling %%~nf.c... %ARMCC_PATH% !COMMON_FLAGS! !INCLUDES! !DEFINES! !OPTIONS! %%f -o .\%OBJ_DIR%\%%~nf.o if errorlevel 1 goto :BUILD_FAILED ) if !ERRORLEVEL! equ 0 ( echo Compilation successful! ) else ( echo Compilation failed with error code: !ERRORLEVEL! ) pause
REM 6、编译汇编文件 echo Assembling startup files... %ARMASM_PATH% --cpu=%TARGET_CPU% --apcs=interwork %SOURCE_DIR%\startup_stm32f10x_hd.s -o %OBJ_DIR%\startup.o if errorlevel 1 goto :BUILD_FAILED echo Assembl successful! pause
REM 7、链接所有目标文件 echo Linking objects... set OBJ_FILES= for %%f in (.\%OBJ_DIR%\*.o) do ( set OBJ_FILES=!OBJ_FILES! "%%f" ) if defined OBJ_FILES ( %ARMLINK_PATH% --scatter="%SCATTER_FILE%" ^ --map --list="%OUTPUT_DIR%\memory_map.map" ^ --output="%OUTPUT_DIR%\%PROJECT_NAME%.axf" ^ --entry=Reset_Handler ^ --info=sizes,totals,unused ^ %OBJ_FILES% if errorlevel 1 goto :BUILD_FAILED ) else ( echo No .o files found! ) echo Link successful! pause
REM 8、生成固件文件 echo Generating firmware files... %fromelf% --bin --output="%OUTPUT_DIR%\%PROJECT_NAME%.bin" "%OUTPUT_DIR%\%PROJECT_NAME%.axf" %fromelf% --i32 --output="%OUTPUT_DIR%\%PROJECT_NAME%.hex" "%OUTPUT_DIR%\%PROJECT_NAME%.axf" echo Generating firmware successful! pause
echo ======================================== echo Build Completed Successfully! echo Output files in: %OUTPUT_DIR% echo ======================================== goto :EOF
:BUILD_FAILED echo. echo ERROR: Build failed at step above! pause exit /b 1
|
上述批处理程序实现了根据所有.c源文件和.sct分散加载文件,通过调用Keil命令行工具,将其编译、链接形成了烧写文件hex、bin。批处理文件中每一步都加了pause,用于显示每一步的结果,实际build时可以无需这些pause,直接生成需要的烧写文件。
运行批处理程序后会在build文件夹下生成烧写文件bin、hex以及map文件。
5.总结
| 任务 | 主要工具 | 关键参数 |
| 编译C/C++ |
armclang、armcc |
-c, -I , -D , -mcpu |
| 编译汇编 |
armasm |
--cpu, -I |
| 链接器 |
armlink |
--scatter , --map , --output |
| 创建库 |
armar |
-r |
| 格式转换 |
fromelf |
--bin, --i32 , --text -c |
| 全自动构建 |
UV4.exe |
-b <project.uvprojx> , -j0 |
熟练掌握 Keil 命令行工具,能够应对自动化测试和生产环境的构建需求。
|