STM32F103_Bootloader开发实战:Keil工程输出路径与文件名的自动化配置与bin文件一键生成
1. 为什么你需要关心Keil的输出路径和文件名如果你正在做STM32F103的Bootloader开发也就是我们常说的IAP功能那你肯定遇到过这样的场景每次编译完工程Keil都会在项目根目录下生成一堆.axf、.map、.lst文件还有各种.o文件散落在各个子目录里。时间一长项目文件夹就变得一团糟想找个最终要烧录的.bin文件得在文件堆里翻半天。更麻烦的是当你需要写一个自动化脚本定时拉取代码、编译、然后生成固件包给生产部门时如果输出文件的位置和名字不固定脚本怎么写都会很别扭容易出错。我自己在带团队做量产项目时就踩过这个坑。早期没注意输出管理每次发布固件都要手动去拷贝、重命名文件不仅效率低还出过两次“拿错版本”的事故差点造成批量返工。从那以后我就把工程输出的规范化配置当作项目启动的第一步必做事项。所以今天咱们不聊复杂的Bootloader跳转逻辑和Flash分区就聚焦一个非常具体、但能极大提升你开发效率和项目规范性的“小事”如何驯服Keil让它乖乖地把编译生成的文件放到你指定的文件夹里并用你指定的名字命名最后还能一键生成直接用于升级的.bin文件。这不仅仅是让文件夹看起来整洁。它的核心价值在于版本管理清晰所有构建产物集中存放和历史版本对比一目了然。自动化集成友好固定的输出路径和文件名是CI/CD持续集成/持续部署流水线能自动抓取固件的前提。减少人为错误避免手动拷贝、重命名过程中可能出现的失误。团队协作统一新成员拿到工程编译后得到的结果位置和所有人一致减少沟通成本。听起来是不是挺有必要的接下来我就手把手带你从零开始配置一个干净、自动化程度高的Keil工程输出环境。2. 第一步给编译输出文件安个“家”默认情况下Keil这里特指MDK-ARM编译产生的文件比如可执行文件.axf、链接列表文件.map、反汇编列表.lst等都会生成在一个叫做Objects的文件夹里针对ARMCC编译器而中间编译生成的.o文件则散落在各个源码目录下的Listings子文件夹里。这种分布对于查看单个模块的编译信息或许方便但对于管理最终产物来说就是一场灾难。我们的目标是把所有最终需要关心的输出文件集中放到一个独立的目录中。我习惯在工程根目录下创建一个名为Output或者Build、Release的文件夹。注意不要在Keil的图形界面里用资源管理器去新建而是通过修改工程配置来实现这样配置信息会保存在工程文件里团队其他成员同步代码后也能自动生效。具体操作如下打开你的STM32F103 Bootloader工程在Keil中点击工具栏的魔术棒按钮Options for Target。在弹出的对话框中选择“Output”选项卡。你会看到一个“Select Folder for Objects...”的按钮。点击它。这时会弹出目录选择对话框。我强烈建议你导航到你的工程根目录然后点击右下角的“新建文件夹”图标创建一个名为Output的文件夹。选中这个新建的Output文件夹然后点击“确定”。回到“Output”选项卡你会发现“Output directory”这一项后面的路径已经变成了你刚才选择的.\Output这里的.代表工程文件所在的目录。完成了这一步你再次编译工程就会发现.axf和.map等文件不再出现在原来的Objects目录而是整齐地躺在了Output文件夹里。这只是第一步我们只是给最终链接后的文件搬了家那些编译过程中产生的.o对象文件和.d依赖文件还在到处乱跑。不过对于Bootloader开发我们最关心的是最终的.axf和后续转换的.bin所以这一步已经解决了核心痛点。如果你想更彻底可以在“C/C”选项卡的“Include Paths”下方找到“Misc Controls”添加--output_dir.\Output\Obj这样的参数来指定对象文件的输出目录但这通常不是必须的。3. 第二步给你的固件起个响亮的名字文件放对地方了接下来就是给它起个好名字。默认情况下Keil生成的可执行文件名字和你的工程名是一样的。比如你的工程叫Bootloader那么生成的.axf文件就叫Bootloader.axf。这看起来没问题但在实际项目中我们可能需要更明确的命名。例如你的工程可能包含两个部分Bootloader工程和Application工程。为了在最终固件包中清晰区分你可能希望Bootloader生成的.axf文件叫Bootloader_V1.0.axf而App生成的叫App_V1.2.axf。这样一看文件名就知道是什么、什么版本。在Keil里修改输出文件名非常简单还是在那个“Options for Target” - “Output”选项卡里。找到“Name of Executable”这一输入框。默认里面是你的工程名。你可以直接修改它。比如改成App或者Bootloader_V1_0。注意这里不需要加.axf后缀Keil会自动加上。我个人的习惯是在这里使用一个“基名”。比如就写App。然后通过后面会讲到的编译后步骤在生成.bin文件时再附加上版本号等信息。这样.axf文件保持简洁而用于发布的.bin文件则包含丰富信息。这里有个小技巧Keil支持在“Name of Executable”中使用一些预定义宏。比如L表示目标名称Target Name也就是你工程左边Project窗口里那个目标的名称。但通常直接输入你想要的固定名字就足够了。修改完名字后点击编译看看Output文件夹里生成的文件是不是已经按你心意改名了。4. 第三步理解核心工具——fromelf.exe前面两步我们解决了“文件放哪”和“叫什么”的问题现在来解决最关键的一步如何得到那个能直接烧录进Flash的.bin文件。Keil编译生成的是.axf文件它包含了调试信息、符号表等丰富内容文件体积较大不适合直接用于固件升级或量产烧录。我们需要的是一个纯二进制镜像也就是.bin文件。这个转换工作Keil自带了一个命令行工具来完成它就是fromelf.exe。你可以把它理解为一个“格式转换器”。它的主要工作就是把链接器生成的、包含ELF格式信息的.axf文件“榨干”水分提取出纯粹的、按地址顺序排列的二进制机器码生成.bin文件。这个.bin文件里没有任何冗余信息单片机CPU可以直接识别和执行。这个工具在哪里呢它就在你的Keil安装目录下。典型路径是C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe如果你用的是ARMCC编译器。如果你用的是AC6ARM Compiler 6路径可能是C:\Keil_v5\ARM\ARMCLANG\bin\fromelf.exe。你可以在文件资源管理器里找到它确认它的存在。fromelf.exe是一个命令行工具这意味着它没有图形界面需要通过命令参数来调用。它的基本语法是fromelf [options] input_file其中input_file就是你要转换的.axf文件。常用的options包括--bin指定输出格式为二进制Binary。--outputfilename指定输出文件的路径和名称。--i32、--i16、--i8指定输出二进制数据的宽度32位/16位/8位通常用默认的--bin即可。--text输出文本格式的反汇编代码这个在分析程序时很有用但不是我们现在需要的。所以一个典型的、用于生成.bin文件的命令长这样C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output .\Output\App.bin .\Output\App.axf这条命令的意思是调用fromelf.exe工具将当前工程目录下Output文件夹里的App.axf文件转换为二进制格式并输出到当前工程目录下Output文件夹里的App.bin文件。你完全可以在Windows的命令行CMD或PowerShell中手动执行这条命令来测试。但我们的目标不是手动执行而是让Keil在每次编译成功后自动帮我们执行这个转换。5. 第四步实现“编译即得bin”的一键式工作流手动敲命令太麻烦而且容易忘。我们要做的是把fromelf命令集成到Keil的构建流程中。Keil提供了一个非常强大的功能User Command用户命令。我们可以在编译完成后自动执行我们预设的命令。这个配置入口依然在“Options for Target”对话框中这次我们切换到“User”选项卡。在“User”选项卡里你会看到“Run #1”和“Run #2”等复选框和输入框。我们主要使用“After Build/Rebuild”区域下的选项。这里的意思是在构建编译链接完成之后执行用户命令。勾选“Run #1”前面的复选框激活它。在“Run #1”后面的输入框里粘贴或输入我们精心构造的fromelf命令。但是这里不能写死绝对路径和固定文件名因为你的工程可能换到别的电脑上或者你修改了输出文件名。我们需要使用Keil的工程变量来让命令更通用、更智能。Keil提供了一些有用的变量比如#L代表最终生成的可执行文件.axf的完整路径但不包含后缀。例如.\Output\App。#B代表最终生成的可执行文件.axf的文件名不含路径和扩展名。例如App。#J代表工程文件所在的目录路径。为了让命令更健壮我推荐使用以下格式$K\ARM\ARMCC\bin\fromelf.exe --bin --output #L.bin #L.axf让我来解释一下这个命令$K这是Keil的内置变量代表Keil的安装根目录例如C:\Keil_v5。使用$K比写死C:\Keil_v5要好得多因为不同电脑的安装路径可能不同。#L.axf这就是我们刚刚编译生成的.axf文件的完整路径带后缀。#L是它的基名我们加上.axf后缀。这样无论你的输出目录和可执行文件名怎么配置这里都能准确地指向刚刚生成的那个文件。#L.bin这是我们希望输出的.bin文件的完整路径。我们把它和.axf文件放在同一个目录#L决定的目录只是后缀名改为.bin。你也可以把它输出到别的目录比如.\Binaries\#B.bin。输入完命令后点击“OK”保存配置。现在你尝试点击Keil的“Rebuild”按钮全部重新编译。编译过程结束后注意观察下方的“Build Output”窗口。在编译信息的最后你应该能看到类似这样的行After Build - User command #1: fromelf.exe --bin --output .\Output\App.bin .\Output\App.axf并且如果一切顺利你会看到.\Output目录下除了App.axf果然多出了一个App.bin文件这就实现了我们梦寐以求的“一键生成bin文件”。6. 第五步高级技巧与避坑指南基本的自动化流程已经搭建好了但在实际项目中你可能会遇到一些更复杂的需求或问题。这里分享几个我积累下来的高级技巧和常见坑点。6.1 为bin文件添加版本信息直接生成App.bin虽然能用但在版本管理时还是不够清晰。我们希望在文件名里体现版本号比如App_V1.0.5_20240515.bin。这可以通过结合Keil的预定义宏和批处理脚本实现。首先你可以在“Options for Target” - “C/C” - “Preprocessor Symbols”中定义一个宏比如APP_VERSION\V1.0.5\。但如何在fromelf命令中使用这个宏呢直接使用是不行的。一个实用的方法是使用一个中间批处理文件.bat。在工程目录下创建一个scripts文件夹里面新建一个post_build.bat文件。在这个bat文件里你可以做更多事情比如从代码头文件中解析版本号或者使用日期命令生成时间戳然后动态拼接出最终的文件名。在Keil的“User”选项卡里不再直接调用fromelf而是调用这个批处理脚本并把必要的参数如#L.axf的路径传递给它。例如一个简单的post_build.bat内容如下echo off REM 接收Keil传递的参数第一个参数是axf文件全路径不含后缀的#L set AXF_BASE%~1 REM 定义版本号实际项目中可以从头文件读取 set VERSIONV1.0.5 REM 获取当前日期 set DATE%date:~0,4%%date:~5,2%%date:~8,2% REM 拼接最终bin文件名 set BIN_NAMEApp_%VERSION%_%DATE%.bin REM 调用fromelf进行转换 C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output %AXF_BASE%_%VERSION%.bin %AXF_BASE%.axf REM 或者输出到单独的Release文件夹并带上日期版本 C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output .\Release\%BIN_NAME% %AXF_BASE%.axf echo Bin file generated: %BIN_NAME%然后在Keil的“Run #1”里输入.\scripts\post_build.bat #L这样每次编译后你都能得到一个包含版本和日期的、规范的固件文件非常适合自动化归档。6.2 处理fromelf工具路径问题如果你团队中成员的Keil安装路径不一致比如有人装在C盘有人装在D盘使用$K变量是最佳选择。但请确保所有人的Keil安装目录结构是标准的fromelf.exe都在$K\ARM\ARMCC\bin\或对应的AC6路径下。有时你可能会遇到“fromelf不是内部或外部命令”的错误。这通常是因为命令路径中有空格且没有用引号括起来。确保你的命令中像$K\ARM\ARMCC\bin\fromelf.exe这样的路径如果包含空格例如Keil安装在Program Files下整个路径必须用双引号包围。但$K变量本身在展开时Keil似乎会处理好空格问题。为了绝对安全可以写成$K\ARM\ARMCC\bin\fromelf.exe --bin --output #L.bin #L.axf6.3 同时生成hex文件除了.bin有时生产烧录也可能需要.hex文件。fromelf同样可以生成hex格式参数是--i32输出Intel 32位Hex格式。你可以在“User”选项卡里启用“Run #2”再添加一条命令$K\ARM\ARMCC\bin\fromelf.exe --i32 --output #L.hex #L.axf这样一次编译就能同时得到.bin和.hex文件。6.4 编译失败时不要执行Keil的“After Build”命令无论编译成功还是失败都会执行。这可能导致在编译出错时仍然试图去转换一个不存在的或者错误的.axf文件产生无用的输出或报错。一个更严谨的做法是只在构建成功时执行转换。这可以通过在批处理脚本中判断Keil传递的构建结果参数来实现但Keil本身没有直接提供这个选项。一个简单的变通方法是观察“Build Output”窗口如果最后有““.axf” - 0 Error(s), N Warning(s).”这样的成功信息才认为构建成功。在批处理脚本中实现这种判断稍微复杂一些对于大多数项目即使编译失败也执行一次fromelf通常会失败影响不大。7. 整合到你的Bootloader开发流程现在你已经掌握了配置Keil自动化输出和生成bin文件的全部技能。让我们把这些点串联起来看看它在完整的STM32F103 Bootloader开发流程中是如何发挥作用的。假设你正在开发一个典型的IAP系统Bootloader工程你首先会创建一个Bootloader工程负责初始化硬件、检查升级标志、跳转到App等。按照本文的方法配置其输出目录为.\Bootloader\Output可执行文件名为Bootloader并设置编译后生成Bootloader.bin。Application工程然后创建主应用程序工程。同样配置输出目录为.\Application\Output可执行文件名可能是App并生成App.bin。这里有一个关键点你需要在App工程的链接脚本.sct文件中将程序的起始地址设置为Bootloader之后的空间例如0x08008000。自动化构建当你需要发布一个版本时你只需要分别打开两个工程点击“Rebuild All”。之后在各自的Output目录下就会得到干净的Bootloader.bin和App_Vx.x.x.bin。固件打包你可以再写一个简单的脚本将这两个bin文件或许还有一个包含版本信息的manifest.txt文件打包成一个Firmware_Package_Vx.x.x.zip。这个打包脚本可以非常确定地从.\Bootloader\Output和.\Application\Output目录找到所需的文件因为路径是固定的。烧录与升级生产烧录时先将Bootloader.bin烧录到MCU的起始地址如0x08000000。之后无论是通过串口、CAN还是USB你的Bootloader程序都会知道从升级包中解压出来的App.bin文件需要被写入到0x08008000这个起始地址。整个流程清晰、自动化、不易出错。文件夹结构整洁脚本编写方便团队协作顺畅。这看似微不足道的配置工作实则是保障项目工程化、专业化的基石。我见过太多因为早期忽视这些“小事”而导致后期维护和升级一团乱麻的项目。希望你能从项目一开始就重视起来把这些最佳实践用上。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2409896.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!