简介这份《IAR 使用手册》面向使用 IAR EWARM 开发 NXP ARM MCU 的初学者、竞赛参赛者与嵌入式课程实验人员解决工程从建立到调试的入门问题。内容按创建工程、添加源代码、配置工程选项、编译链接、下载调试五个环节组织讲清工具链与空模板选择、头文件路径、优化级别、Flash 烧写格式、链接命令文件、调试器驱动、下载模式及 RDI 调试代理等配置并结合 LPC2148 例程与 H-JTAG 调试环境说明。压缩包仅含 1 个 PPT约 806KB便于快速翻阅和课堂展示。已有 510 人学习可作为 2007 年 NXP 中国 ARM MCU 大学设计竞赛参考材料帮助读者梳理 EWARM 工程搭建流程与关键选项含义。1. 一份 2007 年的 IAR 使用手册为什么现在还有人翻手上有一块 LPC2148 的老开发板翻出一份 2007 年写的 IAR 使用手册多数人第一反应是这玩意儿还能用吗。答案是能用而且比新版文档更对口。v4.41A 那一代的工程模型是 .ewp .eww .xcl 三件套跟现在的单文件工程和 icf 链接配置完全是两套东西拿新文档去对照老工程菜单路径一页都对不上。这份手册把「建工程、加文件、配选项、编译链接、下载调试」压成一条最短路径每一步都对应一个具体的勾选项适合手里有 ARM7 板子、需要把调试链路从零打通的人也适合想搞清楚 IAR 工程文件谁管谁、链接脚本管什么的人。它不是教程是一张地图。2. 建工程与工具链选型ARM、Empty project 与 .ewp/.eww 的分工2.1 工具链下拉框选 ARM模板必须选 Empty project启动 IAR 之后第一件事是 Project → Create New Project弹窗里两个下拉框决定后面所有事情。Tool chain 选 ARMProject templates 选 Empty project。工具链选错是最隐蔽的一类错误装了 ARM、AVR、MSP430 三套工具链的机器上选成 AVR 之后打开工程器件头文件全找不到编译第一行就抛Fatal Error[Pe1696]: cannot open source file LPC214x.h看上去像路径配错实际是编译器根本不是那一套。模板这一栏更值得说。IAR 自带的 C main、asm main 之类模板会顺手塞进一个示例 main 和一份通用启动文件新手容易觉得省事但 LPC2148 这类芯片的启动文件不是通用的——向量表要按芯片的中断源数量排布PLL 初始化要按外部晶振频率算 MAM 和 CCLK 分频通用模板里的 cstartup 跑起来时钟是错的现象是全速运行几秒后串口输出全是乱码。Empty project 把所有依赖摊开在明面上缺什么补什么虽然多花十分钟但后面出问题能定位。提示模板选 Empty project 之后工程里是空的连启动文件都没有。这不是漏配是设计如此启动文件要自己从芯片对应的例程目录里拷。2.2 目录怎么摆源码、头文件、链接脚本各归各位工程文件用.ewp后缀保存时 IAR 会问文件名手册里用的是LPC2148_Demo.ewp。这里有个容易混淆的点.ewp是单个工程的配置文件列表、编译选项、链接选项全在里面XML 明文.eww是 workspace作用是把一个或多个.ewp聚合起来同时记住当前激活的是哪个工程、Build 顺序是什么。一个 workspace 挂两个工程比如一个 boot 一个 app是常见做法构建时按顺序执行。老版本 IAR 的.ewp里存的是相对路径基准目录就是.ewp文件所在目录。所以目录结构一旦定下来就别乱挪挪了之后所有源文件的路径全断。我一般会这么摆lpc2148_demo/ ├── LPC2148_Demo.ewp # 工程文件路径基准点 ├── LPC2148_Demo.eww # workspace最后保存 ├── src/ # .c / .cpp ├── inc/ # .h ├── asm/ # .s79 汇编与启动文件 └── config/ ├── LPC2148_flash.xcl # Flash 版链接命令文件 └── LPC2148_RAM.xcl # RAM 版链接命令文件这样摆的好处是.xcl和源码分离切换 RAM 调试和 Flash 调试时只改一个路径不碰源文件。手册里把源文件直接复制到工程目录下能跑通但工程一大就乱。2.3 用 IarBuild 把点击流程复现成一条命令IDE 里点 Rebuild All 是最直观的但要在一台没有图形界面的构建机上复现就得走命令行。IAR 从很早就带了一个叫 IarBuild 的命令行构建器参数不多记住三个就够-build全量重编-make增量编译-clean清理产物。下面这段脚本把工程路径、配置名、日志输出都参数化了#!/usr/bin/env bash # 用法: ./build.sh Debug 或 ./build.sh Release set -euo pipefail CONFIG${1:-Debug} # 安装根目录用环境变量传避免把绝对路径写死在脚本里 IAR_ROOT${IAR_ROOT:?请先设置 IAR_ROOT 指向 Embedded Workbench 4.0 安装目录} IARBUILD$IAR_ROOT/common/bin/IarBuild.exe PROJ$(pwd)/LPC2148_Demo.ewp LOGbuild_${CONFIG}.log # -build: 全量重建-make: 只编有改动的文件 $IARBUILD $PROJ -build $CONFIG 21 | tee $LOG # 从日志里捞错误和警告条数非零直接让脚本失败 grep -E Error\[|Warning\[ $LOG | sort | uniq -c || true脚本里三个参数值得展开说。$1是配置名对应 Options 里 General Options → Target 那一页的 Debug / Release两个配置的优化级别、输出格式、链接脚本通常完全不同所以必须显式传。IAR_ROOT用环境变量而不是硬编码是因为不同机器的安装路径不一样写死之后脚本一换机器就废。tee加grep的组合是为了在 CI 里能拿到退出码——IarBuild 自己会返回非零但被管道吃掉set -o pipefail就是防这个。注意-build和-make的区别不只是快慢。-make依赖时间戳判断如果从别处拷进来一个时间戳比目标文件还旧的源文件它会跳过编译现象是改了代码没生效。血泪经验是切分支之后先跑一次-clean再-build。3. 源码与链接脚本.xcl 内存布局、.s79 汇编与输出格式3.1 LPC2148_flash.xcl 和 LPC2148_RAM.xcl 里到底写了什么手册里在第 2 章和第 3 章两次提到.xcl文件一次是让你从例程目录里拷到工程目录一次是在 Options → Linker → Config 里指定。这两个动作是配套的缺一不可。.xcl是 IAR 老版本的链接命令文件Linker Command File本质是一串给链接器的指令告诉它代码段放哪、数据段放哪、栈顶在哪、中断向量表占多大。以 LPC2148 为例Flash 512KB 映射在0x00000000片内 SRAM 32KB 映射在0x40000000。这两个地址是硬约束写错了链接能过但程序跑不起来。文件里常见的行长这样// LPC2148_flash.xcl 关键行结构示意非厂商原文 -DROM_START0x00000000 -DROM_END0x0007FFFF -DRAM_START0x40000000 -DRAM_END0x40007FFF // 中断向量表固定在 Flash 起始处占 64 字节 -Z(CODE)INTVECROM_START-ROM_START0x3F // 其余代码和常量依次排布 -Z(CODE)CODEROM_START0x40-ROM_END -Z(CONST)CONSTROM_START0x40-ROM_END // 已初始化、未初始化、清零数据统一放 RAM -Z(DATA)DATA_I,DATA_Z,DATA_NRAM_START-RAM_END-D开头的是宏定义给后面引用-Z开头的是段放置规则括号里是段名等号右边是地址区间。INTVEC单独拎出来占 0x40 字节是因为 Cortex-M 之前的中断控制器要求向量表从 0 地址开始且连续跳转指令和向量地址混排会跑飞。RAM 版把ROM_START改到0x40000000代码整体搬进 SRAM。这样做的好处是调试时下载快、断点几乎无限制坏处是一断电全没且可用空间只有 32KB稍微大一点的程序链接就会报Error[Lp011]: section placement failed。配置项Flash 版RAM 版代码起始地址0x000000000x40000000可用代码空间512KB约 32KB与数据段共享掉电保持是否断点数量受硬件断点限制基本不受限下载速度慢逐页擦写快3.2 添加源文件的顺序与 .s79 汇编文件Project → Add Files 支持多选一次把.c、.cpp、.s79全加进去。老版本 IAR 的 ARM 汇编后缀是.s79.s79表示 ARM7/ARM9 指令集早期还有.s26对应更老的核。文件加进去之后在 Workspace 树里按目录分组显示顺序不影响链接结果但影响可读性我一般把启动文件放最上面。启动文件 cstartup.s79 干三件事定义中断向量表、初始化栈指针、跳到 main。它跟.xcl是强耦合的——向量表占了 0x40 字节.xcl里的INTVEC段就必须正好覆盖这 0x40 字节多一个字节少一个字节都会导致CODE段起始地址错位最终现象是复位后第一条指令跳到野地址。添加文件时有个细节容易漏IAR 不会自动把文件所在目录加入头文件搜索路径。源文件加进去了能编译但只要它#include了同目录下的.h就会报找不到。3.3 头文件包含路径与优化级别Options → C/C Compiler → Preprocessor 里填 Additional include directories一行一个支持相对路径相对.ewp。工程小的时候用相对路径工程大了跨机器协作用绝对路径反而更稳因为相对路径一旦有人把目录结构改了所有人都跟着挂。优化级别在 Options → C/C Compiler → Optimizations。老版本的分档是 None / Low / Medium / HighHigh 下面再分偏向速度还是偏向体积。这一栏的选择直接决定调试体验级别适用阶段典型副作用None单步定位、查时序代码体积最大执行慢变量全部可见Low日常开发变量基本可见个别局部变量被寄存器化Medium功能联调函数可能被内联断点位置漂移High (speed)发布循环被展开断点打不上High (size)Flash 紧张同上且单步几乎不可用调试阶段用 High 是最常见的翻车来源明明代码里flag是 1Watch 窗口里显示 0因为编译器把它整个优化进寄存器了内存里那个位置根本没写过。判断方法很简单把优化关掉重编一次现象消失就是优化问题不是逻辑问题。3.4 输出文件simple-code、intel-extended 与那个必须勾上的复选框Options → Linker → Output 这一页有两个开关决定最终产物形态。第一个是 Format。选simple-code生成 IAR 私有格式配合 C-SPY 的 flash loader 直接烧选intel-extended生成标准 Intel HEX给第三方烧写工具用。手册里写得很直白下载到 RAM 调试可以跳过这一步下载到 Flash 调试选 simple-code要生成 hex 给别人烧选 intel-extended 并手工把后缀改成.hex。第二个是Allow C-SPY-specific extra output file。这个复选框不勾除了主输出文件之外的.hex、.map一概不生成现象是 Options 里明明勾了 Generate linker map file目录里就是没有.map。很多人卡在这一步以为是路径写错。注意.map文件是排查内存布局问题的唯一入口不管发不发布都建议常开。它会列出每个段的起始地址、长度、以及 ROM/RAM 的总占用。4. 调试链路RDI Driver、H-JTAG 代理与 flash loader 的握手4.1 为什么选 RDI 而不是 IAR 自带驱动Options → Debugger → Setup → Driver 里那一长串下拉选的是 C-SPY 跟硬件之间说话的协议。这一代 IAR 自带的驱动只覆盖少数几款仿真器手上是 SuperJTAG 这类并口 Wiggler 兼容硬件的话必须走 RDI。RDI 全称 Remote Debug Interface是一层中间规范C-SPY 只认 RDI 接口具体怎么产生 JTAG 时序由第三方代理负责。H-JTAG 就是那个代理它对外暴露H-JTAG.dll同时提供一个常驻的 Server 程序负责占住并口。链条是这样的C-SPY → RDI 接口 → H-JTAG.dll → H-JTAG Server → 并口 → SuperJTAG 转接头 → 目标板 JTAG 排针。任何一环断了都连不上报错信息还都长得差不多。配置顺序不能反。先在 Debugger → Setup 里把 Driver 选成 RDI然后在同一页的 RDI 子项里填H-JTAG.dll的完整路径。这个路径指向 H-JTAG 的安装目录不是拷到 IAR 目录下——拷过去看似省事升级 H-JTAG 之后两份 dll 版本不一致会出现「能连上但下载到一半断开」这种玄学问题。并口地址在 H-JTAG Server 里设LPT1 通常是0x378LPT2 是0x278。设错的现象是 Server 显示已启动C-SPY 也能连上但读芯片 ID 一直返回全 0。4.2 RAM 调试与 Flash 调试的四个开关对照这是整份手册里最容易配错的部分因为四个开关分散在三个页面少配一个都能编译通过只是行为不对。把两组配置并排列出来对照着改比来回翻页靠谱配置位置选项名RAM 调试Flash 调试Linker → ConfigLinker command fileLPC2148_RAM.xclLPC2148_flash.xclDebugger → DownloadUse flash loader(s)不勾勾选Linker → OutputFormatsimple-codesimple-code 或 intel-extendedDebugger → DownloadVerify download可不勾建议勾选Use flash loader(s)这个复选框的语义是「下载时通过一段运行在 RAM 里的小程序去擦写 Flash」。RAM 调试时程序本来就下载到 RAM勾上它反而会让 C-SPY 试图去操作 Flash 控制器轻则报超时重则把本来要下载的段地址算错。4.3 从 Download and Debug 到退出一条完整的操作序列配置齐了之后实际操作只有几个快捷键但顺序有讲究。第一步启动 H-JTAG Server确认它识别到目标芯片 ID而不是显示Not Connected。这一步在 IAR 之外很多人忘了直接在 IAR 里点下载然后对着Failed to connect to target排查半小时。第二步Project → Rebuild All看 Build 窗口最后一行是不是Total number of errors: 0。有 warning 可以先放过有 error 必须清干净因为链接失败的工程下载下去的是上一次的旧产物。第三步CtrlD 触发 Download and Debug。C-SPY 先复位目标然后按.xcl里的段地址把 simple-code 格式的镜像逐段写入Flash 模式下这一步会调用 flash loader 擦除整个扇区。第四步程序停在 main 的入口。此时可以下断点、开寄存器窗口、开 Memory 窗口按地址查看外设寄存器。LPC2148 的 GPIO 寄存器在0xE0028000附近直接跳过去比读手册快。第五步调试结束用 CtrlShiftD 退出。退出时 C-SPY 会问是否复位目标选是否则芯片停在断点处下次上电行为跟预期不一致。5. 避坑排查编译过了、下载成功了、程序就是不跑的五种情形5.1 编译链接阶段现象一改了代码Rebuild 之后行为没变。原因通常是增量编译的时间戳判断失效。从别处拷进来的源文件修改时间可能比目标文件还旧-make直接跳过。另一种可能是工程里同时存在两份同名.c一份在src/一份在根目录IAR 按 Add Files 的顺序取先加进去的那个。解决方法是先-clean再-build然后在 Workspace 树里逐个核对文件路径。养成习惯切分支、拉代码、换机器之后第一次构建一律走全量。现象二Error[Lp011]: section placement failed说明某段放不下。原因分两种。选了 RAM 版.xcl但代码超过 32KB是最常见的一种另一种是.xcl里的ROM_END和芯片实际容量对不上比如拿的是 256KB 版本的配置去链接 512KB 的芯片反过来更糟链接器认为放得下实际写到不存在的地址。解决方法是先看.map文件里各段的累计长度再核对芯片型号后缀。LPC2148 的 Flash 是 512KB如果 map 里CODE段已经到 0x0007A000那就别再往里塞了。5.2 下载握手阶段现象三C-SPY 报Failed to connect to target或一直读不到芯片 ID。原因按概率排H-JTAG Server 没启动并口地址设成了0x278而机器上是 LPT1目标板处于 ISP 模式——LPC2148 的 P0.14 在上电复位时被拉低会进入片内 bootloaderJTAG 直接不响应并口被别的程序占用老式打印机驱动、某些采集卡软件都会抢。解决方法是按这个顺序查Server 界面有没有识别到 ID没有就查线有线但 IAR 连不上就查 dll 路径都对就查 P0.14 电平把跳线拔了再上电。现象四下载到 99% 卡住然后超时。Flash 调试时出现多半是 flash loader 的时钟配置跟目标板实际晶振不匹配。loader 是跑在目标芯片上的它靠内部 RC 或者外部晶振起振晶振没起振它就跑不动。另一种可能是芯片被读保护了擦除命令返回失败但界面只显示超时。解决方法是先用第三方串口 ISP 工具全片擦除一次确认芯片没锁再检查目标板晶振是否真的在振示波器看别靠猜。5.3 运行阶段现象五下载成功全速运行立刻进 HardFault 或者直接跑飞。原因几乎总是链接脚本和实际下载方式不匹配.xcl选了 RAM 版代码起始 0x40000000但Use flash loader(s)勾着程序被烧进 Flash 的 0x00000000复位后 CPU 从 0 地址取指取到的却是空白 Flash 的 0xFFFFFFFF译码成未定义指令。解决方法是把 4.2 那张对照表逐行核一遍尤其是链接脚本和 flash loader 这两个必须同进同退。核完还是跑飞就看.map里INTVEC段的起始地址是不是0x00000000。6. 进阶把点击流程固化成脚本加一份上电前的检查清单手工点二十几次 Options 配一个工程配第二块板子的时候还得重来一遍这是最没必要的重复劳动。老版本 IAR 的.ewp是 XML 明文可以直接复制改写配合前面那个build.sh把 Debug / Release 两套配置的差异做成两份.ewp模板新工程从模板起只改文件列表和.xcl路径。更进一步可以把「构建 产物校验」串成一步。下面的脚本在编译完成后检查 map 文件的段占用超阈值直接失败#!/usr/bin/env bash # 在 build.sh 之后执行校验内存占用是否超出芯片实际容量 set -euo pipefail MAP$(find . -name *.map -newer LPC2148_Demo.ewp | head -n1) [ -z $MAP ] { echo 未找到 map检查 Allow C-SPY-specific extra output file; exit 1; } # 抓 ROM 与 RAM 的总占用字段位置随 IAR 版本略有差异用 grep 兜底 ROM_USED$(grep -iE ^\s*[0-9]\s[0-9]\s.*readonly $MAP | awk {s$1} END{print s0}) RAM_USED$(grep -iE ^\s*[0-9]\s[0-9]\s.*readwrite $MAP | awk {s$1} END{print s0}) ROM_LIMIT$((512*1024)) RAM_LIMIT$((32*1024)) echo ROM: ${ROM_USED} / ${ROM_LIMIT} RAM: ${RAM_USED} / ${RAM_LIMIT} [ $ROM_USED -gt $ROM_LIMIT ] { echo ROM 超限; exit 1; } [ $RAM_USED -gt $RAM_LIMIT ] { echo RAM 超限; exit 1; } exit 0find -newer用来定位本次构建产生的 map避免拿到上一次的旧文件这个坑我在多配置工程里踩过不止一次。两个grep的正则按 map 里段的读写属性筛不同 IAR 版本的列顺序有差异awk累加第一列是基于「长度列在最前」这个常见排布如果对不上就打开 map 人工看一眼列头再改。最后是一份上电前的检查清单五条照着过一遍能挡掉八成问题检查项判据链接脚本与下载方式一致RAM 版配不勾 flash loaderFlash 版配勾选向量表落在 0 地址map 里 INTVEC 段起始为 0x00000000ROM/RAM 未越界脚本输出的两个比值都小于 1H-JTAG Server 已识别芯片 ID不是 Not ConnectedP0.14 未被拉低上电时该引脚为高否则进 ISP写这份东西的时候我把手上三块板子的配置全推翻重配了一遍起因是有一次赶进度RAM 版.xcl忘了换回 Flash 版程序烧进去怎么都不跑示波器、万用表、换芯片折腾了一下午最后发现是链接脚本里一个地址。从那以后我每次切调试模式都会先把 4.2 那张对照表从头到尾核一遍核完再点下载。希望帮到你。本文还有配套的精品资源点击获取