ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Keil生成bin文件全攻略:C51与ARM工程配置详解(含错误排查)

Keil生成bin文件全攻略:C51与ARM工程配置详解(含错误排查) 用Keil做完固件拿到的却是一堆.hex文件等到要做bootloader升级、要做量产批量烧录、或者想看看固件到底多大时往往就卡住了。这个场景我碰到过好几回项目调通了但给生产那边交付固件对方开口就问“bin文件呢”那一刻才知道原来在很多烧录工具、产测软件、IAP升级流程里bin才是通用语言hex反而不那么受欢迎。其实Keil MDK本身是能直接生成bin文件的但有一个前提你得“告诉”它一声。C51和ARM两个平台在设置上有相似之处但细节和坑完全不同。这篇文章我会把Keil C51和ARM也就是MDK-ARM两种方式的完整操作、命令参数、常见报错全部捋一遍顺便把bin文件怎么打开、怎么校验、J-Flash怎么用它烧录这些周边工具也一并讲清楚。无论你是刚碰单片机的新手还是已经被“CreateProcess failed”折磨过的老手这篇都能帮到你。1. 为什么非得要bin文件它和hex到底差在哪1.1 hex与bin本质上是两种“格式逻辑”很多人第一次接触bin文件是在下载固件时看到“bin文件怎么打开”之类的搜索然后发现Windows双击根本打不开就误以为文件坏了。其实bin不是给“打开看”用的它是给单片机执行用的。做一个最直白的对比hex文件是文本文件里面每一行都包含了地址、数据和校验码而且这些内容都是ASCII字符bin文件则是纯二进制去掉了一切外壳只留下最原始的机器码数据。对比项HEX文件BIN文件文件内容ASCII文本含地址、类型、数据、校验纯机器码二进制流是否自带地址信息自带每行都记录地址不带需要指定加载地址是否能直接“看”用记事本能打开能看到字符必须用十六进制编辑器查看烧录时工具按地址逐行写入工具按固定起始地址连续写入文件体积通常比bin大30%或更多最小和实际固件大小相当bin文件相当于把hex里的数据区全部“拆开”、去掉地址再按顺序连成一片。这意味着烧录bin时你和烧录工具之间必须有一个约定——起始地址是多少。这个约定一旦错固件刷进去就是跑飞、死机、黑屏。1.2 哪些场景非用bin不可你可能觉得hex也能烧录为什么非要纠结生成bin我用实际经历告诉你下面这几个场景用bin会顺手得多Bootloader App升级架构IAP升级时boot区接收的固件包通常是bin因为App运行地址是固定的上位机只需要把bin从SPIFlash/SD卡读出来直接跳到固定地址执行就行。hex自带地址反而多余。量产烧录产线用的烧录夹具包括J-Flash、ST-Link批量烧录软件多数对bin支持更友好尤其是当固件需要先做加密、合并、CRC校验时bin结构简单处理起来最不容易出错。固件体积评估看hex文件大小没有任何意义因为里面包含大量文本字符。比如一个实际固件只有30KBhex文件可能达到60KB以上。而bin文件的体积就是真实固件大小做OTA升级判断“分多少次发完”就靠它。OTA差分升级做差分升级时需要对比新旧固件的差异这时候只能用bin格式因为hex的地址和校验信息会干扰比对结果。所以生成bin看似是个小功能实际上是很多项目流程里的硬需求。早点把Keil里这条链路打通省得每次都快交付了才手忙脚乱。2. 两种生成方案fromelf转换和hex转bin工具2.1 方案一Keil自带的fromelf.exe这是MDK-ARM内置的转换工具全名是“ARM ELF Format Conversion Tool”位置在Keil安装目录下的ARM子目录里。以常见的MDK5安装路径为例C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe C:\Keil_v5\ARM\ARMCLANG\bin\fromelf.exe注意上面出现了两条路径这直接对应两种编译器版本ARMCC是ARM Compiler 5AC5ARMCLANG是ARM Compiler 6AC6。很多人在网上找教程复制了一条fromelf路径过来结果一运行就报错“CreateProcess failed”十有八九就是编译器版本和路径不匹配。fromelf的作用是把编译链接后生成的axf文件ARM可执行文件转换成别的格式包括bin、hex、elf、文本汇编等。它的核心用法是fromelf --bin --output目标.bin 源.axf我测试过很多次这个命令最稳定参数不需要多多了反而容易出问题。2.2 方案二第三方hex转bin工具对于C51工程情况稍微复杂一点。Keil C51的编译器是C51.exe链接器是BL51.exe或LX51.exe它本身没有集成fromelf。虽然可以在Output选项卡里勾选“Generate ELF/DWARF Information”来生成axf文件再用ARM目录下的fromelf处理但很多人觉得这样绕。更简单的办法是直接用第三方小工具把Keil已经生成的hex文件转成bin。这类工具里我比较常用的是hex2bin以及srec_cat。hex2bin老牌小工具单文件命令行执行支持Keil生成的Intel HEX和Motorola HEX格式。srec_cat来自SRecord工具集功能更强大支持格式多还能做CRC校验、地址偏移、文件合并。用法示例hex2binhex2bin.exe -e bin 目标.hex执行后会在同目录下生成和hex同名的bin文件。用srec_cat的话srec_cat.exe 目标.hex -Intel -o 目标.bin -Binary两条命令效果一样就是把hex里的数据区重新排列成连续的二进制流。2.3 两种方案怎么选我个人的建议是ARM工程优先用fromelf毕竟这是官方工具链的一部分不需要额外下载任何东西可靠性最高。C51工程推荐用hex2bin或srec_cat因为C51的常规流程里本来就要生成hex直接在hex基础上转bin最省事不需要额外勾选生成axf也不容易因为配置问题报错。如果追求统一C51工程也可以在Output里勾选生成axf然后用ARM目录下的fromelf统一处理。但有些版本的C51编译器生成的axf用新版本fromelf转换会有兼容性小问题所以为了稳定C51我默认走hex转bin路线。3. C51工程生成bin的具体操作3.1 C51工程让Keil先输出hex文件C51工程默认编译后只会生成OMF51格式的目标文件也就是.OBJ与.LIB并不会自动生成hex。要在Keil C51里生成hex需要手动打开“Output”选项卡勾选“Create HEX File”。具体操作如下在Keil中打开C51工程鼠标右键点击目标选择“Options for Target”切换到“Output”选项卡勾选“Create HEX File”重新编译编译完成后在Output文件夹里就能看到.hex文件。这一步比较简单但要注意如果Keil版本是评估版且没有正确授权C51编译出来的代码会被限制在2KB以内这时候生成的hex也不完整烧录进去跑不起来。这个限制跟生成bin没有关系是编译器授权层面的问题遇到“2K限制”请优先检查许可证。3.2 C51工程用hex2bin转换成bin拿到hex文件后打开命令行Windows CMD切换到hex文件所在目录执行hex2bin.exe app.hex如果不指定输出参数hex2bin默认会生成一个和输入文件同名的.bin文件。如果你想明确指定扩展名可以加“-e bin”参数hex2bin.exe -e bin app.hex执行之前检查一下当前目录下有没有正在被其他程序占用的同名bin文件有的话先关闭占用程序否则会报“Permission denied”。转换完成后用十六进制编辑器打开bin文件看一眼开头几个字节正常应该能看到C51启动代码里的跳转指令比如“02 00 00”这类。如果你看到开头全是FF或者一堆乱码先别急着烧录大概率是hex文件本身有问题或者转换参数不对。3.3 C51工程也可以用fromelf转bin有时候你手上没有现成的hex转bin工具或者不想下载第三方软件C51其实也可以借助ARM的fromelf来完成转换前提是C51工程能生成axf文件。方法是在Output选项卡里多勾选一项“Generate ELF/DWARF Information”重新编译后工程目录下会生成.axf文件。然后使用ARMCC目录下的fromelf命令C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --outputapp.bin app.axf这个操作在MDK5的C51工程里实测可用但有两点需要注意必须勾选“Generate ELF/DWARF Information”否则axf文件不会生成fromelf版本和C51生成的axf兼容性在个别老版本上可能有异常如果转换出来的bin大小和预期严重不符建议还是用hex转bin路线。3.4 C51串口升级架构里bin文件要特别留意地址如果你做的项目是C51单片机串口升级架构boot app那bin文件的地址问题一定要提前想清楚。C51的boot区通常放在低地址比如0x0000~0x0FFFapp区从0x1000或更高地址开始。生成app的bin时它内部的代码地址是按app编译时的地址来生成的烧录时也必须烧到对应位置。很多人在网上问“c51架构中boot和app的中断处理”问题通常就出在app的起始地址设置以及中断向量表偏移上。比如说app区的基地址是0x1000那么app的bin前4KB区域实际上是留给中断向量表的但bin文件里从头到尾就是一个连续的数据流它不知道什么叫“偏移”。你在烧录时把bin写到0x1000那bin开头的4KB自然就成了中断向量区正好映射到芯片的中断向量地址。如果烧录时地址写错哪怕偏差1个字节中断一进来就会跑飞。所以C51生成bin后请务必做好三件事确认编译时Target标签里的“Off-chip Start Address”和烧录地址一致打开map文件找到“C_STARTUP_START”“C_STARTUP_MAIN”等标号确认入口地址在预期范围内在IAP上位机或Bootloader烧录时严格指定固定的烧录起始地址。map文件平时可能没人注意但在bootapp这种多段地址架构里它就是排查问题的第一手资料。4. ARM工程生成bin的完整操作4.1 先搞清楚你的ARM编译器是AC5还是AC6ARM工程生成bin的主要思路是使用fromelf但“用哪个fromelf”取决于你工程的编译器版本。在Keil MDK中打开“Options for Target”切到“Target”选项卡看“ARM Compiler”下拉框显示“Use default compiler version 5”或“ARM Compiler 5.06”那你的工程用的是AC5fromelf路径在C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe显示“Use default compiler version 6”或“ARM Compiler 6.x”那你的工程用的是AC6fromelf路径在C:\Keil_v5\ARM\ARMCLANG\bin\fromelf.exe。两个版本的fromelf命令语法基本一致但路径完全不同。网上有很多教程只写了ARMCC路径如果你用的是AC6直接套用就会报错。4.2 在Keil里配置“编译后自动生成bin”手动每次执行命令比较烦我建议直接把生成bin的动作挂到Keil的After Build事件里。这样每次编译完成bin文件自动就出来了。具体步骤打开“Options for Target”切到“User”选项卡在“After Build/Rebuild”区域勾选第一项“Run #1”在后面的输入框里填入命令记得勾选“Run #1”前面的复选框否则命令不会执行。命令行写法有两种我用的是带引号的完整路径最稳妥C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output.\Objects\app.bin .\Objects\app.axf如果你的工程输出目录不是Objects就改成实际的输出目录。注意Keil的默认输出目录取决于Target名如果你在“Output”选项卡里改了“Select Folder for Objects”那就以那个实际目录为准。还有一种写法是利用$L和$L这两个Keil内置宏它们分别代表生成的axf文件完整路径和所在目录可以让命令不依赖固定目录适合工程拷来拷去的情况C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output$LL.bin $LL.axf我个人实际使用时更喜欢“L”这个写法因为当工程名或Target名变化时不需要反复改脚本。4.3 一条命令看懂fromelf参数fromelf参数不多但每个都值得理解清楚否则改个需求就不知道怎么调了。用一个表来总结参数作用示例--bin输出bin格式--bin--output文件指定输出文件名--outputapp.bin--hex输出hex格式--hex--text输出文本反汇编--text -c--32bit生成32位地址格式的镜像--32bit--base地址设置bin的加载基地址--base0x08000000大多数情况下生成bin只需要--bin --output这两个参数。如果遇到某些Bootloader要求bin文件必须从某个特定地址加载那可以用--base来设置加载地址。举一个带base参数的完整例子C:\Keil_v5\ARM\ARMCLANG\bin\fromelf.exe --bin --base0x08000000 --outputapp.bin .\Objects\app.axf这里设置base为0x08000000适用于STM32这类Flash起始地址0x08000000的芯片。如果你的芯片Flash基地址不同比如0x00000000就改成自己的值。4.4 用J-Flash烧录bin文件时要注意什么很多人在生成bin之后会用到J-Flash来单独烧录尤其在做产测或者离线烧录时J-Flash几乎是标配工具。J-Flash打开bin文件时会弹出一个对话框问加载地址Load Address。这里必须填你芯片Flash的起始地址。以STM32F103为例填0x08000000。如果你填成0数据会被写到地址0x00000000对于大多数ARM芯片来说这相当于写到了System Memory或Boot ROM里程序根本起不来。加载bin之后可以在J-Flash里点击“Target Manual Programming Program”执行烧录。烧录前建议先做“Blank Check”或者“Erase Sectors”否则Flash里残留的数据可能会和bin数据混在一起看起来程序烧进去了但运行结果完全不对。J-Flash还可以从芯片里反向读取bin文件连上芯片后在“Target Read Back”里选择读取整个Flash然后“File Save Data As”保存为.bin。这个功能常用来做固件备份或对比“烧进去的和生成的bin是否一致”。我建议生成bin后养成一个习惯——用J-Flash烧录后回读再和原始bin做一次16进制比对百分之百确认固件正确性。5. 高频问题排查与配套工具5.1 报错“CreateProcess failed”怎么处理这是ARM工程配置After Build命令时最经典的一个报错完整信息大致是这样的*** Error: CreateProcess failed, Command: c:\keil_v5\arm\armcc\bin\fromelf...造成这个错误的原因不外乎这几类路径不对C盘是不是真的在那个位置是不是D盘安装的Keil如果路径是错的命令根本执行不了。可以先打开资源管理器找到fromelf.exe复制它的实际完整路径替换上去。AC5和AC6路径混用AC5的fromelf在ARMCC目录AC6的在ARMCLANG目录。如果你工程是AC6却填了ARMCC路径同样报这个错。路径带空格且没加引号Keil默认安装在C:\Keil_v5通常没空格但如果你自定义安装到了C:\Program Files\Keil路径里的空格会让命令解析出错必须用双引号把整个路径包起来。杀毒软件拦截某些安全软件会把fromelf的自动调用当成“可疑行为”拦截导致进程创建失败。这种可以先关闭实时防护再重新编译试试。权限问题Keil安装在C盘但某些UAC策略下命令行无法在工程目录创建bin文件。这种情况可以把工程挪到非系统盘或者以管理员身份运行Keil。排查时先在命令行手动执行一遍这个命令看能不能成功。能成功说明是Keil侧配置或权限问题不能成功就先怀疑路径和参数。5.2 bin文件怎么打开和校验bin文件本身没有文件头整个文件就是数据所以Windows自带记事本、图片查看器都打不开。想正确查看bin文件建议用十六进制编辑器。我常用的有HxD免费、绿色、轻量打开大文件也不卡适合日常查看和比对010 Editor功能强支持模板解析、二进制比对适合专业分析UltraEdit老牌编辑器列模式、十六进制查看都很顺手。打开bin文件后怎么判断它是不是你想要的固件有几点经验看开头几个字节ARM Cortex-M芯片的bin文件开头通常是中断向量表前4个字节是初始栈指针SP后4个字节是复位向量Reset Handler。比如STM32工程开头大概率是00 00 00 20之类的栈指针值复位向量指向Flash地址通常以0x0800xxxx的形式存在。看文件末尾正常bin文件末尾没有固定标记如果你发现末尾有一大段连续的FF可能是Keil从编译起始地址到Flash末尾全部填充了说明你的bin文件里包含了大量空白区域而不仅仅是实际代码大小。看文件大小是否和map文件吻合打开map文件的“Memory Map of the image”部分能看到代码段的起始地址和结束地址算一下差值和bin文件大小对比一下偏差太大就说明有异常。5.3 Keil中C51和ARM并存不影响bin生成“keil5兼容c51和stm32安装”也是很多人关心的问题而且它直接关系到bin生成工具链是否正常。实际上C51和ARM本来就是Keil MDK的两个独立工具链只要安装时分别选择对应组件即可。安装完成后“Options for Target”里会出现“Device”选项卡选择不同芯片会自动切换对应的编译器。唯一要注意的是安装顺序。官方推荐先安装C51的Keil安装包再安装MDK-ARM的安装包或者反着来。实际操作中我建议直接分别下载“Keil C51”和“MDK-ARM”两个安装包装到同一个目录下比如都装到C:\Keil_v5这样两个工具链会共享同一个UV4.exe入口工程文件也能互相通用。如果安装到不同目录虽然也能用但切换工程时容易因为路径问题出乱子。两个工具链并存之后C51工程的fromelf处理可以继续用ARMCC目录下的那个不影响。ARM工程则根据编译器版本自己找路径。两个工具链互不干扰这也是我推荐大家直接装到一起的原因。5.4 工具下载与替代方案生成bin需要的工具优先级我先说清楚fromelf不需要单独下载装好Keil MDK自带hex2bin单文件工具名字就是“hex2bin”网上很多网站提供下载下载时注意看文件大小和来源优先选择GitHub或知名嵌入式论坛的资源srec_catSRecord工具集里最常用的一个支持Linux/Windows功能强大适合批量处理固件时使用。如果你不想装任何额外工具还有一个思路在Keil的“After Build”命令里直接调用python脚本脚本解析hex文件输出bin。但这属于杀鸡用牛刀我不推荐常规使用。最后再分享一条实用经验生成bin后千万不要只看文件存在就算完事。我的习惯是每次编译完顺手在命令行执行一次hexdump -C app.bin | head -20看一眼开头数据和文件大小确认无误后再拿去测试或交付。这一步用不了10秒钟但能挡住绝大多数“固件烧进去莫名其妙不跑”的低级问题。毕竟bin文件不像hex那样自带地址和校验信息出问题时排查链路更长不如在生成环节就把住关口。
返回列表