首页 / 资讯中心 / 文章详情

IAR嵌入式开发极简入门:从新建工程到下载运行

IAR嵌入式开发极简入门:从新建工程到下载运行 ★ FEATURED ARTICLE
第一次打开IAR Embedded Workbench时很多人都会愣一下菜单一排接一排图标全是英文缩写界面看着老气横秋可偏偏不少芯片原厂的SDK、例程包默认就带IAR工程。我当时也是一样对着它发了半天呆点开一个菜单发现里面又套了好几层子菜单愣是找不到类似新建文件这种直觉入口。后来做嵌入式的时间长了才反应过来IAR真正高频用到的功能其实就那么几个菜单、那么几步顺序剩下的大多数功能对日常开发来说根本碰不到。这篇文章不打算把IAR讲全也讲不全目标只有一个让刚拿到IAR的人在今天下班之前能把一块新板子编译通过、下载进去、跑起来。整个流程我会拆到每个菜单、每个选项顺带把那些当年要是有人直接告诉我就好了的坑都摊开讲。你不需要懂编译器原理也不需要背快捷键跟着点就行。1. 先搞清楚IAR的本职工作它不是一个普通编辑器1.1 IAR在嵌入式流程里到底扮演什么角色很多人第一次用IAR会下意识把它当成一个类似记事本、或者类似网页编辑器的工具以为写代码才是核心任务。这是最初级的误解。IAR Embedded Workbench是一个完整的集成开发环境也就是说编辑代码只是它最不重要的功能之一它真正干的事情是把C语言代码编译成能在特定芯片上跑的机器码然后把这份机器码通过调试器烧进芯片再帮你做断点调试、变量查看、寄存器观察。打个比方记事本只能让你写出菜谱的文字而IAR是一整套厨房它负责把菜谱变成能端上桌的菜甚至还能让你尝尝咸淡。在整个嵌入式开发流程里IAR处在写代码和芯片运行之间承担了编译、链接、烧录、调试四件大事。所以你会看到它有编译器选项、链接器选项、调试器选项这些在普通编辑器里根本不存在。那为什么很多项目非要用IAR而不是其他工具我遇到过几种典型场景第一种芯片原厂提供的SDK和参考例程只给IAR工程尤其是某些工业级、车规级或老牌芯片厂商他们官方的BSP默认就是在IAR下测试的你换别的工具链反而要自己折腾工程配置第二种IAR的编译器在代码密度和优化效果上确实有口碑同样的代码用IAR编译出来的Flash占用经常比GCC小一点这对Flash紧张的芯片很关键第三种纯属历史项目遗留公司多年积累的代码和脚本都建立在IAR上新人不适应也得适应。1.2 认识.eww、.ewp、.icf这个三件套IAR的工程文件和别的IDE不太一样有几个后缀名你会反复看到建议一开始就记熟。.eww是工作区文件全称大概可以理解为IAR Workbench Workspace它是最大层的容器一个.eww里可以放多个.ewp工程。.ewp是具体的工程文件里面记录了该项目用了哪些源文件、芯片型号是什么、编译选项怎么设。.icf是链接脚本文件它告诉链接器芯片的Flash从哪里开始、RAM有多大、代码段怎么排布。严格来说是.icf或者.xcl新版本IAR普遍用.icf。新手最容易犯的一个操作错误是在文件夹里看到一个.ewp文件就双击它结果打开后发现工程里啥都没有或者路径全部错乱。正确做法是双击.eww工作区文件让整个工作区加载进来。如果只有一个工程IAR在新建工程时也会默认生成一个同名工作区所以你只要找.eww双击就行。这一点虽然听起来很简单但我亲眼见过有人因为只打开.ewp文件折腾了半小时认为工程损坏。还有一点要记住IAR工程文件里的源文件路径通常记录的是相对路径但相关配置里如果用到了绝对路径非常容易出问题。后面讲到include路径时会专门展开。2. 极简六步从新建工程到听见下载完成的提示音2.1 新建空工程时必须选对工具链打开IAR之后第一步不是急着写代码而是新建工程。菜单路径是Project Create New Project。此时弹出一个对话框左边是工具链列表右边列了一些模板你需要先选左侧的芯片架构再选右侧的模板。这里非常关键工具链一定不能选错。比如你的芯片是ARM Cortex-M内核就选ARM这一大类如果是AVR就选AVR如果是Renesas的某些内核会有对应的独立工具链。选中之后再在右侧模板里选Empty project也就是空工程。不要选那些带main之类的模板因为模板里生成的启动文件、头文件路径不一定匹配你手上的芯片反而制造麻烦。保存工程文件时路径选择也有讲究。我的建议是工程目录不要带中文不要带空格尽量放在一个层级简单的路径下比如D:\work\demo1。原因后面解释但你现在先照着做能省很多事。2.2 给工程选芯片型号这一步决定了后面一半的报错新建完成后左侧Workspace窗口会出现你的工程名。右键点击工程名选择Options在弹出的配置对话框里找到General Options这一项再切到Target标签页。这里有一个Device下拉框里面是按厂商、系列、型号组织的芯片列表。这一步一旦选对IAR会自动帮你处理很多事预定义正确的芯片宏、选用匹配的内核启动文件、把寄存器定义的头文件路径配置好。很多人在这一步随便选了个内核比如芯片其实是Cortex-M4他选了个Cortex-M0结果编译报出几百个未定义错误其实根源就在这里。如果你在列表里找不到自己的芯片型号先别慌。有几种可能一是你的芯片太新当前IAR版本还没支持这种情况下要么升级IAR版本要么选一个内核相同、外设相近的替代型号临时凑合二是你下载的IAR版本对应的厂商插件没装全。一般情况下主流芯片在IAR自带的Device列表里都能找到找不到再考虑换版本或加补丁。选完型号后Options对话框先别关后面还有几个要配置的地方我们一步步来。2.3 添加一个最精简的main.c现在只需要一个源文件就能跑起来。在Workspace窗口右键点击工程名选择Add New File这时会弹出新建文件对话框。需要特别注意的是IAR的新建文件默认是没有扩展名的你必须在保存时手动输入main.c把后缀名写清楚否则编译器不认识这个文件。一个能通过IAR编译的最小C程序是这样#include stdint.h volatile uint32_t delay_count 0; int main(void) { while (1) { delay_count; } }这段代码没有任何外设操作但它能验证整个工具链是否通畅编译、链接、烧录、运行。为什么函数里要放一个无限循环因为MCU的main函数正常情况就不该返回如果你在main函数最后加一条return 0;编译器不会报错但进调试模式你会发现程序跑飞了。关于delay_count变量为什么加volatile简单说就是防止编译器优化掉这个变量后面调试观察时能看到数值变化。如果你选择的芯片型号正确你在整个工程里甚至不需要自己写启动文件、不需要写链接脚本IAR会在后台自动带上匹配该Device的启动文件和初始化代码。这一点很多新手不知道以为自己必须去复制一份启动文件进工程然后莫名其妙多出一堆链接错误。2.4 把调试器选对Driver和接口别搞混代码写完之后先别急着编译去确认一个非常容易忽略的设置调试器。右键工程名再次打开Options左侧找到Debugger这一大项右侧Setup标签页里有一个Driver下拉框。这个下拉框就是你手里那个烧录工具的类型。常见的调试器包括标准SWD接口的J-Link类仿真器、STM32板子自带的ST-LINK类、以及各种CMSIS-DAP类调试器甚至还有国产芯片原厂出的烧录器。你必须在这里选择对应的驱动类型IAR才能用正确的方式跟你的硬件通信。选错之后最常见的现象是编译和链接都通过了一下载就报错说找不到仿真器。这里有个细节我直到用了很久才注意到Options对话框里左侧既有Debugger这个大项又有Debugger下面的JTAG或C-SPY子项。很多人第一次进来只改了大项的Driver结果连接时候还是用默认的JTAG方式而实际上板子只引出了SWD不认JTAG。你需要在Debugger展开项里找到对应的接口设置一般会有一个Interface选项改成SWD即可。绝大多数现代板子走SWD两根线就够了JTAG那套四线五线在消费级板子上反而不常看到。2.5 Compile All之后先学会看Messages设置都做完第一次编译建议用完整编译。菜单路径是Project Compile All也可以直接按F7。编译过程中IAR底部会弹出Messages窗口里面滚动显示正在编译哪个文件、有没有警告、有没有错误。你需要学会看这个窗口的层级结构。不同版本的IAR显示风格略有差异但基本逻辑差不多错误信息用红色标识警告用黄色标识且每条信息前面有文件路径和行号。双击红色错误信息IAR会自动跳到对应源码的出错位置这比你自己一行行去找快得多。第一次编译零错误零警告是很常见的因为空工程本身就没什么内容。但如果你看到错误别急着改代码先看错误的密集程度。如果报错全部集中在device.h、stdint.h这类系统头文件里多半是Device型号没选对如果报错集中在你自己写的main.c里比如某个变量未声明那才是你自己代码的问题。这一条排查思路可以帮你节省大量时间。2.6 下载运行CtrlD之后会发生什么编译通过之后离点亮就差最后一步了。把调试器接好板子在IAR里按CtrlD或者点击工具栏上那个绿色的Download按钮。IAR会先启动调试会话如果弹出一个类似是否初始化所有外设的选项框保持默认即可。第一次下载会明显慢一点底部进度条会显示擦除Flash、写入Flash、校验的过程。这个过程中板子上的调试器指示灯会闪烁几秒钟后如果一切正常IAR会进入调试界面程序停在main函数的入口处等待你的下一步指令。到这一步肯定有人要问要不要自己按F5让程序跑起来我的建议是如果只是验证下载成功确实可以按F5让它在后台全速跑但这里其实有一个很多人都会踩的坑我会在第四节详细展开。现在先记住一个基本认识CtrlD是下载并进入调试F5是全速运行F10是单步执行到下一行。3. Options里真正值得动的配置按优先级排就四个3.1 优化等级Debug阶段建议选None或Low工程能跑通之后很多人会开始研究IAR的各种优化选项。我的建议非常明确如果你还要调试代码优化等级就不要开太高。在Options对话框左侧找到C/C Compiler右侧切到Optimization标签页你会看到一个Level下拉框里面有None、Low、Medium、High、Size这几种选项。None是完全不优化Size是偏向缩小代码体积。为什么调试阶段要选None或Low因为优化之后的机器码和源码不是一一对应的你明明在源代码第30行设了断点运行起来它可能直接跳到第40行或者你观察某个局部变量Watch窗口告诉你变量已优化不可见非常影响排查。我见过一个真实案例开发者在Release配置下开了High优化程序跑起来功能一切正常但某个变量在代码里明明被赋值了用调试器读出来却不是那个值最后排查半天发现是编译器把两条看似无关的语句做了重排和合并。这个案例不是说优化不好而是说你需要知道优化对调试的影响。日常开发我的做法是Debug配置用Low准备发布固件时再单独建立一个Release配置把优化开到High或Size。顺带一提IAR的工程可以配置多个构建配置在Project Edit Configurations里可以新增默认有Debug和Release两个。Debug和Release不只是优化等级不同还涉及调试信息是否包含、宏定义是否切换建议一开始就把这两个配置理解成两套独立参数不要混着用。3.2 Additional include directories找不到头文件都看这里写嵌入式代码几乎不可能不使用芯片厂商提供的SDK头文件。SDK解压之后你会得到一堆分散在多个目录下的.h文件。如果你在代码里写#include chip.h编译却报错说找不到这个文件十有八九是这个选项没配好。在Options左侧选C/C Compiler右侧切到Preprocessor标签页里面有一个Additional include directories输入框。把这个框里填入你的头文件路径多个路径用分号分隔。这里有个非常实用的变量$PROJ_DIR$它代表当前工程文件所在的目录。比如你的SDK解压在工程目录下的Drivers文件夹里头文件又在Drivers/Inc那你就填$PROJ_DIR$\Drivers\Inc。用这个变量填的好处是整个工程拷贝到其他电脑、其他路径下只要相对结构不变路径就不会失效。我见过太多人直接写绝对路径比如D:\mysdk\include然后整个工程丢给同事编译直接报红。原因就是同事电脑上SDK根本不在D盘。所以从第一天开始尽量养成用$PROJ_DIR$和相对路径的习惯。同理源文件的添加也尽量通过Workspace窗口的Add Existing File让IAR维护相对路径而不是手动复制.c文件。3.3 生成hex/bin文件从只在IDE里烧变成能发布固件在IDE里下载程序当然很方便但你总不能要求生产线的同事也装一个IAR然后把工程文件发给他让他按下载按钮。实际生产中固件交付通常要给一个烧录文件也就是hex或bin格式用独立烧录工具写进芯片。哪怕只是自己留着备份生成一份hex文件也比保留整个Debug目录靠谱。在Options左侧找到Linker右侧切到Output标签页默认选中Allow C-SPY-compatible output这是给IDE内调试用的。要生成烧录文件你需要勾选Other然后在下面的Output format下拉框里选Intel extended也就是Intel HEX格式。如果你想生成纯二进制bin文件可以选binary这时通常还需要在Output file区域勾选Override default并把扩展名改成.bin。为什么生成bin有时需要手动加扩展名因为IAR默认输出文件名和工程名一致但扩展名不一定是你想要的烧录工具对扩展名敏感。我用得最多的还是hex格式因为hex里包含地址信息烧录工具可以自动分配到正确地址而bin是裸数据烧录时你必须手动指定起始地址搞错就直接砖。所以如果你是新手优先选Intel extended生成hex。3.4 下载方式与Flash Loader别让代码只在RAM里跑还有一个很多人没意识到的选项藏在Debugger Download标签页里。一个叫Use flash loader的选项默认是勾选的它的作用是让IAR在下载程序时先把一小段烧录程序加载到芯片RAM里再由这段程序把应用代码写进Flash。只要你是正常的Flash烧录这个选项保持勾选就行。但如果你的程序是调试在RAM里运行的比如做Flash边读边写的实验不希望代码本身占着Flash那这里就该考虑不同的下载方式。另外有个选项Verify download建议勾选它会在烧录完成后把芯片Flash里的内容读回来和电脑上的文件做比对这一步能非常有效地发现接线不稳定或者供电不足导致的写入异常。我觉得Verify download是唯一一个我会建议所有项目都保持勾选的选项。要注意的是Debugger里还有一个Flash Loader子页面里面列出了当前芯片型号对应的烧录算法文件。如果你换了一个芯片型号但这里面的列表没有自动更新下载时可能报错说Flash没有匹配的loader。这时候回General Options Target重新确认Device型号然后让IAR重新生成配置。4. 极简流程最常见的烧录失败我按这三个层次排查4.1 物理链路驱动、接线、供电如果你确认编译链接都正常但一按下载就报错请先不要怀疑IAR配置按顺序检查硬件链路。第一层是电脑有没有识别到调试器。打开设备管理器如果你在端口或通用串行总线控制器里看到带黄色感叹号的未知设备基本就是驱动没装或者没装对。这种情况和IAR没有任何关系你需要先把调试器的驱动装好。第二层是物理接线。以最常见的SWD接口为例你需要保证SWDIO、SWCLK、GND三条线一定要接对VCC在某些调试器上不是必须但很多板子供电不稳这时候连上VCC让调试器供电反而更稳。我遇到过好几次下载失败最后发现是杜邦线松了SWCLK那根线虚接接触不良导致时好时坏。建议接线之后轻轻拉一下每根线确认不是靠运气接触。第三层是目标板供电。某些低功耗板子只靠调试器的3V3供电带不动尤其是带屏幕、带无线模块的板子一擦除Flash电流上来电压就被拉低下载直接失败。这种时候要外接电源并且把地和调试器共地。不要觉得这一点太基础我自己就栽过跟头一个带OLED的小板子在IAR里下载时反复报target connection lost最后发现是单独供电后就好了。4.2 芯片匹配Device型号、ID、电压物理链路没问题接着查芯片匹配。最常见的是Device型号选错或者选成类似型号IAR在连接芯片时会读取芯片的ID并和Device配置里的预期ID做比对。如果ID不匹配它会提示芯片型号不匹配或者干脆报no target connected。还有一种情况在某些调试器上会遇到电压设置不对。IAR的Debugger设置里有一些驱动支持配置通信电压如果板子实际工作电压是3.3V你设定成5V通信电平对不上下载必定失败。这个选项通常在Debugger展开项下对应驱动型号的页面里比如J-Link页面就有Communication相关设置选USB即可而Target相关电压在硬件上通常由调试器自动检测但老式调试器可能需要手动拨码或设置具体看你手里的硬件。另外还有个隐藏杀手芯片被写保护或读保护了。某些芯片一旦使能了读保护调试器就无法正常连接表现和找不到芯片几乎一样。如果你之前做过读写保护实验现在突然怎么都连不上芯片先想办法用原厂工具解除读保护而不是反复在IAR里试。4.3 工程与烧录配置路径、输出格式、优化硬件查完、芯片型号确认完之后就要回到IAR工程里看配置了。第一是路径问题工程路径带中文、带空格在某些IAR版本里会导致编译器无法定位临时文件报出一堆莫名的编译错误不是你的代码问题纯粹是路径字符问题。解决办法很简单把整个工程移到纯英文路径下再打开。第二是输出格式问题你在Linker的Output里选择了生成hex文件但下载时IAR可能仍然试图使用旧的调试输出文件导致报错说文件不存在。这时候在Project Clean清一次工程再重新Compile往往就能解决。如果还是不行检查Debugger Setup页面里的Use command line之类的设置看它指定的文件名和工程名是否一致。第三是优化等级导致调试信息混乱它不会直接让下载失败但会造成下载成功之后程序不在main停下的现象。如果你的优化等级是High断点命中位置变得飘忽不定甚至Run to main选项失效不要惊慌先把优化等级降下来再试。4.4 这张排查对照表值得打印出来我这里把从按下CtrlD到成功进入调试界面之间可能遇到的典型报错整理成一张表对应的排查动作也一并写下现象/报错排查优先级最可能原因找不到调试器/无法建立连接第一优先驱动未装、USB线只供电不通数据NO target connected第一优先SWD接线松动或接错、芯片供电不足芯片型号ID不匹配第二优先Device型号选错或选成系列内近似型号擦除超时/Flash下载失败第一优先接线不稳定、供电不足无法加载Flash Loader第二优先Device型号未正确匹配或换芯片后未重新生成Download校验失败第一优先供电不稳导致写入数据位错误下载成功但程序不运行第三优先优化等级过高、main函数被优化成空壳报错文件路径含中文第三优先工程路径或用户名含中文/空格这张表的顺序是有讲究的先解决连接问题再解决匹配问题最后才怀疑配置和代码。我见过有人花了整整一个下午排查Linker配置最后发现其实是调试器的USB线坏了换了根线就好了。硬件问题永远排在软件问题前面这是嵌入式调试的铁律。5. 极简版之上的三个顺手习惯5.1 用一个.eww管好boot和app两个工程当你手头有一个Bootload工程、一个App工程、甚至还有一两个测试工程时最忌讳的就是每次用到哪个就打开哪个.ewp。正确做法是建立一个顶层.eww工作区文件把这些工程全部加入到同一个工作区里点击工程名右键可以设置哪个是活跃工程。这样你可以在App工程里写代码编译前一键切换到Boot工程烧写引导程序再切回来编译App全程不需要关闭工程重新打开。这个习惯对日常工作非常有用尤其是需要同时维护多个固件版本的时候。操作也很简单在任意一个打开的.eww里右键选择Add Existing Project把其他.ewp加进来即可。如果你一开始新建工程时IAR自动生成了.eww那么后续所有工程都可以往这个.eww里加。5.2 调试时把Watch窗口用起来刚学会下载程序的人最爱用的是全速运行加板子上的现象来判断程序对不对比如LED亮没亮、屏幕显示正不正常。这没有错但一旦现象不对你就陷入猜的境地了。我的建议是尽早建立源码级调试的习惯在怀疑的代码行设置断点程序跑到那里停下然后打开View Watch窗口把变量拖进去观察值。IAR的Watch窗口很有几个实用细节。一是在暂停状态下右键某个变量选择Add to Watch可以实时看到它的当前值二是数组和结构体可以展开查看内部每个成员三是当你单步执行时变量值如果发生变化它会高亮显示。这些功能做调试时是真正的帮手比到处抹printf的效率高很多。如果你发现变量在Watch窗口里显示灰色、写着not in scope说明你当前停的位置不在这个变量的作用域内这是正常的把断点往后挪到变量所在函数里再看就行。5.3 换芯片后先Clean再编译最后分享一个我自己的小习惯只要代码工程换过芯片型号或者从别的电脑拷贝过来打开之后第一次编译前一定会先执行Project Clean再执行Compile All。原因是IAR会把很多中间文件缓存在工程目录下的Debug、Release、Settings等文件夹里换芯片型号或换电脑后这些缓存文件和当前配置不匹配偶尔会导致编译报一些非常诡异的错误比如找不到某个中间文件。Clean的作用就是把上一次构建留下的中间产物全部删除让IAR从头开始编译一遍。代价只是多等一两分钟编译时间收益是几乎消灭了一整类莫名其妙的编译问题。同样的道理给别人传工程文件时我也会把Debug和Release目录删掉再打包只保留源码、.eww、.ewp和.icf别人打开后Clean一次就能正常编译。还有一个小习惯是关于备份的IAR工程目录里那些.dep、.o、.out文件都是构建产物体积大且容易和新增源文件产生路径冲突备份代码时不要把它们拷进去。如果你用的是版本管理工具尽早把Debug/、Release/、Settings/加入忽略列表这些目录里的文件放到版本库里只会让每次提交充满噪音也容易在多人协作时产生莫名其妙的冲突。说到底IAR的极简使用流程并不复杂新建空工程、选对芯片型号、写一个main.c、选对调试器、编译、下载。真正让新人卡住的往往不是某一个功能不会用而是流程里的某个小环节没配对然后因为不理解报错含义而陷入乱试。把上面这几步按顺序走一遍遇到问题再回到第四节那张表逐层排查绝大多数情况都能自己解决。剩下的就是在反复调试中逐渐把IAR的那些隐藏功能变成肌肉记忆了。
阅读完成 · 觉得有帮助?
咨询建站