☰
IAR中文手册速查:AVR工具链、C-SPY调试与链接排错
2026/10/27 14:21:48 网站建设 项目流程

简介:《IAR中文用户手册-官方版》面向使用IAR Embedded Workbench IDE进行嵌入式开发的工程师与学习者,尤其适合基于Atmel AVR微处理器开展项目、需要系统查阅工具链用法的人群。它以PDF形式交付,压缩包共1个文件、约859KB,体量轻便,便于随查随用。手册内容覆盖产品介绍与教程两大部分:前者梳理IDE、C-SPY调试器及其调试系统、C/C++编译器、汇编器、XLINK连接器、XAR库创建器与XLIB库管理器等组件;后者从新建应用工程、编译连接、C-SPY调试,到C与汇编混合编程、C++应用及中断模拟逐步展开,可帮助读者理解工程组织、调试流程与混合编程要点。目前已有3380人学习,适合作为AVR嵌入式开发过程中查阅IDE功能、排查编译调试问题的中文参考。

1. 一份 200 多页的 IAR 中文用户手册,先别从头读:三类人三种翻法

手上这份 IAR 中文用户手册官方版 PDF,是 AVR 平台上 IAR Embedded Workbench IDE 的随附文档,正文从产品介绍、七件套工具链讲起,再进教程:建工程、编译连接、C-SPY 调试、C 与汇编混合、中断仿真、库模块引用。它的价值不在“读完”,而在“查得准”——一个.xcl模板写错、一个断点打不上、一个.map里段地址对不上,翻对页三分钟解决,翻错页能耗一下午。刚接手 AVR 项目的新人、从别的 IDE 迁过来的熟手、要给团队定工具链规范的人,三种人翻法完全不同。下面按我实际用它的顺序拆。

2. 工具链七件套与安装目录:把手册第一部分压缩成两张对照表

第一部分是整份手册里最容易被跳过、但出问题时最常回翻的部分。它不讲语法,只讲“这个 IDE 由哪些可执行文件拼起来、它们各自吃什么文件、吐什么文件”。把这一层搞明白,后面所有报错你都能立刻定位到是哪一件工具在抱怨。

2.1 从 IDE 外壳到 XLINK:七件套各自负责哪一段

手册 1.1 节把工具链拆成七块:集成开发环境外壳、AVR C/C++ 编译器、AVR 汇编器、XLINK 连接器、XAR 库创建器与 XLIB 库管理器、C-SPY 调试器、编辑器与工程管理器。原文那句“不同架构,同一解决方案”说的就是这套外壳可以挂不同芯片的后端,工程文件格式和操作习惯不变,换芯片只换编译器后端和器件描述文件。

按实际编译流程排一遍更清楚:源文件.c/.cpp/.s90交给编译器或汇编器,各自产出可重定位目标文件.r90;XLINK 把若干.r90和库文件.a连起来,按.xcl里的段命令摆放代码和数据,输出可执行文件.out和下载格式;C-SPY 再读.out里的调试信息,把源码行、变量、调用栈对回你的编辑器窗口。

组件在工程里干什么手册位置出问题先看哪
IDE 外壳工作区/工程管理、编辑器、构建系统1.1.1工程选项是否落到组/文件级
C/C++ 编译器优化、扩展关键字、DLIB/CLIB 选择1.1.4优化等级、器件型号、头文件路径
汇编器重定位宏汇编,内置 C 预处理器1.1.5段声明、PUBLIC/EXTERN
XLINK 连接器段定位、库模块抽取、类型检查1.1.6.xcl文件、CSTACK 尺寸
XAR / XLIB建库、列模块、增删替换模块1.1.7库顺序、重复符号
C-SPY 调试器断点、变量、调用栈、宏1.1.2、1.1.3驱动选错、优化过高
编辑器/工程管理语法着色、书签、多文件搜索1.1.1基本不用查

选型上有个常被忽略的点:手册明确说编译器、汇编器、连接器都能在命令行单独跑。这句话的含义是,你完全可以把 IDE 当编辑器用,把构建放进批处理或持续集成脚本里,iccavr编译、xlink连接、cspybat起调试会话,三件事可以分开做。团队里多人协作时,我一般会把这套命令行固化成一个build.bat,工程文件只作为选项的“可视化编辑器”,避免有人手改.ewp造成配置漂移。

提示:手册里对 C-SPY 的描述分“主要部分”和“驱动部分”两层,前者是通用的断点/变量/调用栈逻辑,后者负责跟具体目标通信。排查问题时先分清是内核层不工作(源码对不上、变量看不到)还是驱动层不工作(连不上目标板),能省掉一半无效操作。

2.2 安装目录的分层逻辑:avr 与 common 两条分支

手册 1.2.1 节写得很细,但真正需要记住的只有一句:avr目录放芯片相关的东西,common目录放所有产品共享的东西。默认根目录形如x:\Program Files\...\Embedded Workbench 4.n,4.n是 IDE 版本号,安装路径允许自定义,所以任何写死路径的脚本迟早会翻车——我一般让脚本从环境变量读根目录。

# 典型安装后的目录骨架(实际路径以本机为准) $IAR_ROOT/ ├── avr/ │ ├── bin/ # iccavr 编译器、汇编器、C-SPY 驱动等可执行文件 │ ├── config/ # *.xcl 连接模板、*.sfr 寄存器描述、*.ddf 器件描述、*.cfg 着色 │ ├── doc/ # 本手册、编译器参考手册、CHM 在线帮助、readme.htm │ ├── inc/ # 标准库头文件、器件寄存器头文件 │ ├── lib/ # 预编译库与库配置文件 │ ├── src/ # 可配置库源码与示例 │ └── tutor/ # 手册教程对应的示例工程 └── common/ ├── bin/ # xlink、xlib、xar 等共享工具 ├── config/ # IDE 全局设置 ├── doc/ # 连接器与库工具参考手册 ├── plugin/ # 可加载插件 └── src/ # 共享插件源码,如自定义输出格式示例

这张表比死记目录名有用:avr\config是你查“为什么这个器件选不到”“为什么中断向量编号不对”的第一站;avr\doc\readme.htm记录的是手册没来得及写进去的版本差异,装完先扫一眼能省不少事;avr\tutor里放着教程用到的完整工程,第 3 章照着做卡住时,直接拿它对照选项页最省时间。

avr\lib和avr\src的关系也值得说明:编译时链的是lib里的预编译库,但库的源码在src里。当你想弄清某个库函数为什么占了这么多 flash,或者想自己改一版裁剪过的库,就去src里找对应模块,用 XAR 重新建库,再把工程里的库路径指过去。这一步手册提了一句,实际项目里做低功耗或小容量芯片时非常常用。

2.3 文件扩展名与 config 目录里的四类模板

手册 1.2.2 节给了文件类型对照。工程相关的核心是这几个:工作区.eww、工程.ewp、调试器设置.ewd、C 源文件.c、C++ 源文件.cpp、汇编.s90或.asm、头文件.h、可重定位目标.r90、库.a、可执行.out、下载格式.hex/.d90、链接映射.map、列表.lst。

avr\config下的四类模板文件更关键,它们决定了工程能跑起来的下限:

扩展名作用什么时候需要动它
.xcl连接器命令模板,定义段布局、堆栈尺寸、内存区域改 CSTACK/HEAP 大小、自定义段地址、外扩存储
.sfr特殊功能寄存器描述器件寄存器定义不全、需要补自定义外设
.ddfC-SPY 设备描述,仿真器的外设模型软仿真时需要外设行为、中断向量表核对
.cfg编辑器语法着色配置自定义关键字高亮,纯体验项

工程模板.ewp也在config下,新建工程时选择模板,本质就是复制一份预置选项的工程文件。团队里如果要统一编译选项,把自己的.ewp放进这个目录做成模板,比每次口头叮嘱“记得开 map 输出”靠谱得多。

最后有个容易踩的细节先说在前面:手册特别提醒,命令行跑 XLINK 时列表(映象)文件默认扩展名是lst,会和编译器生成的.lst列表文件撞名,后写的直接覆盖前面的。解决办法很简单,在连接选项里把映象文件写成完整名字,比如project1.map,别偷懒用默认值。这条我吃过一次亏,调试时翻了半天“列表文件怎么没有源码行”,最后发现是同名覆盖。

3. 从空工作区到 C-SPY 跑通:建工程、读 map、下断点的完整顺序

第二部分是教程,从新建工程一路走到中断仿真。它的行文是“点这里、再点那里”的流水账,照着做能通,但不知道为什么这么点。这一章我按配置的依赖顺序重排一遍,把每个选项页里真正影响结果的参数挑出来说。

3.1 新建工程与选项配置的先后顺序

顺序错了会反复返工。正确的依赖链是:器件型号决定可选的中断向量和可用内存,内存布局决定.xcl,.xcl决定 CSTACK/HEAP 上限,优化等级和调试信息决定 C-SPY 能看到什么。所以配置必须自上而下,从器件开始。

第一步,新建工作区(Workspace),再在其中建工程(Project)。工作区是容器,一个工作区可以挂多个工程,做 bootloader + 应用的组合时用得上。建工程时选模板,空工程、带 main 的 C 工程、汇编工程各一份,选错了不要紧,删掉源文件重新加就行。

第二步,打开工程选项,在 Target 页选定具体器件型号。这一步不是给你看的,是给编译器和 C-SPY 用的:编译器据此选正确的寄存器头文件和指令集子集,C-SPY 据此加载对应的.ddf。器件选错最典型的表现是编译能过、仿真时寄存器窗口一片空白或者外设名字对不上。

第三步,General Options 页设置目标核心、数据类型和堆栈。堆栈这里只填“期望值”,真正生效的是.xcl里的段定义,两边不一致时以.xcl为准。很多人改了这里发现没效果,就是没意识到这一层。

第四步,C/C++ Compiler 页。优化等级建议开发期用低等级或关闭,量产前再切到尺寸优化复测;列表文件勾上,出问题时能看到生成的汇编;预处理器定义里放板级宏,别把硬件差异写死在源码里。

第五步,Assembler 页,只有混合编程时才需要细调,主要是宏定义和列表输出。

第六步,Linker 页。勾选覆盖默认.xcl,指定实际使用的连接模板;勾选生成链接映射文件,并显式命名成.map。这一步不做,后面排查内存问题会很被动。

第七步,Debugger 页选驱动。软仿真选 Simulator,接硬件仿真器选对应型号。驱动不同,可用的断点类型和数量完全不同,这个后面细说。

第八步,把源文件加进工程组,按 Make 编译。工程支持组级和文件级选项覆盖,做多型号共用一个工作区时,把差异放在文件级,比维护多份工程省事。

; 典型 .xcl 片段(示意,实际以 avr\config 下对应器件模板为准) -D_CSTACK_SIZE=0x100 ; C 栈大小,按最深调用链和局部变量估算 -D_HEAP_SIZE=0x40 ; 堆大小,不用 malloc 就压到最小 -Z(DATA)CSTACK+_CSTACK_SIZE ; 把 CSTACK 段定位到内部 RAM 顶端 -Z(DATA)HEAP+_HEAP_SIZE

.xcl文件里的-D是定义符号,-Z是段定位命令。参数怎么改:先看.map里 CSTACK 段的实际占用峰值,再把_CSTACK_SIZE留出三成余量。压得太狠,程序在中断嵌套深的时候跑飞;给得太大,小容量芯片直接链接报内存不足。这个值没有普适数字,只能靠 map 实测。

3.2 编译连接产物与 map 文件的读法

一次成功构建会产出一堆文件,认识它们比背命令有用。.r90是每个源文件对应的可重定位目标,.out是最终可执行文件并携带调试信息,.hex或.d90是烧录格式,.map是链接映射,.lst是编译器生成的汇编列表。

.map是这里面信息密度最高的。它通常包含模块汇总、段汇总、程序内存汇总和入口列表四块。模块汇总告诉你每个.r90贡献了多少代码和数据;段汇总告诉你每个段被放在哪个地址区间、长度多少;程序内存汇总给出 flash 和 RAM 的总用量,这一行直接决定你能不能换更小容量的芯片。

map 里的区块你该关注什么典型异常
模块汇总哪个模块代码量异常大某个库函数被整段链入,本该被裁剪
段汇总CSTACK、HEAP、.data的起止地址栈段被放到 RAM 末尾但没留够余量
程序内存汇总flash 与 RAM 用量百分比超过 90% 时后续加功能就会撞墙
入口列表复位入口与中断向量地址向量地址与器件手册对不上,多半器件选错

读 map 有个习惯值得养成:每次构建后扫一眼程序内存汇总的 RAM 用量,涨得离谱就去段汇总里找是哪个段变胖了。曾经有个工程 RAM 一夜之间多了两百字节,最后定位到一个调试用的字符串数组忘了删,const也没加,直接落在.data里,跟着启动代码一起从 flash 拷到 RAM。

3.3 用 C-SPY 软仿真跑起来:断点、变量窗口、调用栈

C-SPY 的驱动决定了你能做什么。手册 1.1.3 节列了几类:软仿真驱动完全用软件模拟处理器行为,不需要硬件,适合逻辑验证和没拿到板子的阶段;硬件仿真器驱动面向实时运行,不占目标存储器,断点能力各有差异——其中一类提供四个硬件断点加不限数量的软件断点,另一类支持串口或 USB 连接并内置 flash 下载器。选驱动时别只看“能不能连上”,还要看它是否支持代码覆盖,几类硬件驱动明确不支持代码和数据覆盖,需要做覆盖率统计时只能退回软仿真或换方案。

# 命令行启动一次调试会话(参数名以本机安装版本为准) cspybat iccavr.exe cspySim.dLL \ --debug_file=project1.out \ --device=ATmega128 \ --plugin="avrEquipment.dLL"

这段命令的意思是:用编译器可执行文件加载 C-SPY 的仿真驱动动态库,指定待调试的可执行文件、器件型号和仿真外设插件。参数说明上,--debug_file必须指向带调试信息的.out,指向.hex是没有源码级调试的;--device要与工程选项里选的器件一致,不一致时寄存器窗口会错位;插件参数决定仿真器是否加载外设模型,不做外设仿真可以去掉。

断点分三类:代码断点停在某条语句,可以附加条件,比如i == 100才停,避免在循环里反复中断;数据断点监视某个变量或内存地址被读写;宏断点则挂一段 C-SPY 宏,在命中时执行打印、改变量、甚至注入中断。第三类在中断仿真里是主力,手册 2.5 节专门讲了中断和断点中宏的用法。

变量窗口的坑主要在优化上。开了高等级优化,局部变量可能被完全放进寄存器,窗口里显示“不在作用域”,单步也会在源码行之间跳跃。开发期把优化关掉,或者把关键变量加volatile并在观察窗口里用表达式固定住,比反复怀疑调试器有用。

调用栈窗口依赖编译器生成的扩展调用信息,手册说即使程序计数器停在任何位置也能显示完整调用栈。实际用的时候注意栈回溯在中断上下文里可能断掉,这时候看反汇编窗口更实在。混合显示模式可以同时看到 C 源码和对应汇编,定位“这行 C 到底编译成了什么”时非常高效。

4. 混合编程、中断仿真与库裁剪:手册里最容易被跳过的三节

教程的后半段(2.3 到 2.6)讲的是三件在真实项目里天天遇到、但很少有人系统学过的事:C 调汇编、中断怎么在没硬件时验证、库该链多少。这三节文字不多,信息密度却最高。

4.1 调用规则与汇编模块接入

C 和汇编混编的第一个门槛不是语法,是调用约定:参数放哪、返回值放哪、谁负责清栈、哪些寄存器必须保护。手册 2.3.1 节的建议是先检查调用规则再动手写,这话不是客套。规则没弄清就写汇编,最容易出现“C 里传进去的值在汇编里读出来是垃圾”。

常见做法是先用 C 写一个空函数,编译后看.lst里的汇编列表,观察参数是怎么搬进寄存器的、返回值放在哪、函数序言和尾声长什么样。照着自己编译器实际生成的代码去写汇编模块,比照搬任何文档都准。

; 汇编模块示例:两字节无符号加法,演示段声明与符号导出 NAME ADD16 RSEG CODE:CODE:NOROOT(0) ; 放入代码段,NOROOT 表示无引用时可被裁剪 PUBLIC add16 ; 导出符号,C 端才能链接到 add16: ADD R16, R18 ; 低字节相加(寄存器分配以调用规则为准) ADC R17, R19 ; 高字节带进位相加 RET ; 返回值在 R16:R17 END

这段代码的关键在三个地方:RSEG声明段名和属性,段名和属性写错会导致连接时找不到或放错存储区;PUBLIC导出符号,没有它链接阶段一定报未定义外部引用;寄存器编号必须和调用规则一致,上面只是示意,真实项目要按编译器实际约定填。C 端的声明写法也要对上:

/* 汇编模块的 C 端声明,告诉编译器别做名字修饰 */ extern unsigned int add16(unsigned int a, unsigned int b);

参数和返回值的类型要与汇编里实际操作的数据宽度匹配。用unsigned int而汇编只处理了单字节,高字节就是脏数据。加汇编模块到工程的步骤是:把.s90文件加入工程组,检查该文件的 Assembler 选项是否继承了工程级设置,然后重新构建,用.map确认模块确实被链进去了。

4.2 中断句柄与仿真环境搭建

中断这块,手册 2.5 节的思路很值得学:先加中断句柄,再建仿真环境,最后触发中断验证。它默认你已经知道向量表怎么排,实际上多数人卡在第一步——句柄写了,中断就是不进。

句柄的写法有两种,用编译器扩展关键字声明函数为中断类型,或者用#pragma指定向量。两种方式的区别在于向量编号是显式写死还是由器件头文件里的宏给出。我一般用后者,器件换了向量号自动跟着变,不容易错。句柄函数里不要做耗时操作,不要调用不可重入函数,不要忘了清中断标志——这三条是中断跑飞的经典原因。

仿真环境搭建的核心是把中断源“造”出来。软仿真驱动提供中断模拟能力,配合 C-SPY 宏系统可以在指定时刻手工触发某个向量。步骤大概是:在仿真器配置里启用中断模拟,在需要触发的断点处挂一个宏,宏里写入触发向量的动作,然后全速运行。手册 2.5.4 节讲的“中断和断点中宏的使用”就是这套流程。

宏的写法要注意两点:一是宏里改动的变量和寄存器在中断上下文里的可见性,二是宏执行失败时不会给你明显报错,只是“什么都没发生”。调试时可以在宏里加一条打印,确认宏真的被执行了,再去看中断有没有进。

4.3 库模块:DLIB 与 CLIB 的取舍

手册 1.1.4 节提到两套运行库,这是选型时最实际的一个决策点:

维度DLIBCLIB
标准符合性支持 ISO/ANSI C 与 C++不完全兼容 ISO/ANSI C
浮点支持 IEEE 754 格式不支持
C++支持不支持
代码体积较大较小
适用场景需要标准库完整性、浮点、C++flash 紧张、纯 C、无浮点

选型逻辑很直接:用 C++、用浮点、用标准库里的重函数,就选 DLIB;芯片 flash 只有几 KB、纯 C、定点运算,选 CLIB 能省下可观空间。切换在编译器选项里改一行,但改完必须全量重编译,混着链会出类型不匹配的报错。

XAR 和 XLIB 的用法手册 1.1.7 节讲得比较简略,实际流程是:把若干.r90用 XAR 打包成.a,用 XLIB 列出、添加、替换、移除模块,需要时把模块在程序和库类型间转换。链接时 XLINK 只抽取被实际引用的模块,这就是为什么库大了不一定占 flash——但前提是每个模块粒度够细。如果你的库把十个函数塞进一个模块,用一个就全链进来,.map里立刻能看出来。遇到这种情况,重新按功能拆分源文件再建库,比事后优化代码有效得多。

5. 排查清单:编译连接与调试仿真两个阶段的高频翻车

这份手册的价值有一半在排错,但它按功能组织,不按症状组织。下面这些是我和同事实际撞过的,按“现象 → 原因 → 解决”记下来,对照着查比逐页翻快。

5.1 编译与连接阶段

现象:编译全过,链接报未定义外部引用,符号名还带着奇怪的前后缀。原因:C 端调用汇编模块或 C++ 调用 C 函数时名字修饰没对上,汇编里也没写PUBLIC。 解决:先在.map或链接报错里看清它找的符号全名,回头核对 C 端声明和汇编导出是否一致;C++ 调 C 要加外部 C 声明块,汇编模块确认PUBLIC拼写和大小写。这类问题九成是名字问题,不是逻辑问题。

现象:明明开了列表文件输出,打开.lst里却没有源码行,只有一堆二进制。原因:连接器生成的映象文件默认扩展名也是lst,把编译器产物覆盖了。 解决:连接选项里把映象文件显式命名成project1.map之类的独立名字,别用默认值。养成构建后先看文件时间戳的习惯,能第一时间发现覆盖。

现象:链接报内存区域溢出,但代码量看着不大。原因:常量数组没加const,落在.data段,启动时要从 flash 拷到 RAM,双份占用;或者某个库模块整段被链入。 解决:打开.map的段汇总看.data和.bss谁在膨胀,把只读数据加const放进 flash;再看模块汇总,找那个异常大的模块,拆库或换精简实现。

现象:换了个器件型号,工程能编译,但中断完全没反应。原因:器件选项没改,编译器用的还是旧头文件,向量号对不上。 解决:Target 页重新选器件,清理后全量重编译。器件相关的宏和向量表都在头文件里,增量编译不会重读,必须清理。

5.2 调试与仿真阶段

现象:单步调试时执行行在源码里乱跳,变量窗口显示变量不在作用域。原因:优化等级开太高,局部变量被放进寄存器或直接被消除,语句被重排。 解决:调试配置单独建一套,优化关掉,需要长期观察的变量加volatile,或者改用表达式窗口按地址观察。发布配置保持优化,两套配置分开维护,别来回改同一个工程。

现象:软仿真里中断句柄永远不执行,硬件上却是好的。原因:仿真环境没启用中断模拟,或者触发宏没真正执行。 解决:确认仿真器配置里中断模拟已开启,在宏里加打印验证宏被执行;再核对向量号和句柄声明是否匹配。手册里“中断和断点中宏的使用”那一节就是为这个场景写的。

现象:程序跑一段时间就复位或行为异常,仿真器里看不出错。原因:CSTACK 给小了,深层调用或中断嵌套把栈写穿,踩到了其他变量。 解决:.xcl里加大 CSTACK,把大数组从局部变量改成静态或放到堆;构建后固定看一眼.map里栈段余量,别等出事才查。

现象:换到硬件仿真器后,代码覆盖率报告出不来。原因:所选驱动不支持代码覆盖,手册在产品介绍里对几类硬件驱动明确标注了这一点。 解决:需要覆盖率时退回软仿真跑用例,或者改用支持该功能的调试方案。选驱动前先想清楚这一轮调试要什么能力,别等做完才发现拿不到数据。

6. 把 PDF 变成随手可查的私人索引:标签、摘录与一条检索习惯

手册是 PDF,目录页码和阅读器物理页码之间有一段偏移,直接输页码经常差几页。我的做法是先花十分钟把一级、二级标题在阅读器里全部建成书签,命名规则统一成“症状关键词 + 章节号”,比如“栈溢出 1.2.1”“未定义外部引用 2.3.1”。建完之后这份文档就从“要读的书”变成了“能查的手册”。

第二步是把文字层抽出来做全文检索。PDF 有文字层时,命令行工具比阅读器搜索快得多,尤其是要跨多个文档找同一个词:

# 抽取文字层,保留分页信息,便于回查页码 pdftotext -layout iar_avr_ug_zh.pdf iar_avr_ug_zh.txt # 按现象检索,一次命中多个候选段落 grep -n -E "未定义|溢出|向量|断点" iar_avr_ug_zh.txt | head -40 # 需要看上下文时,按行号取前后若干行 sed -n '1200,1260p' iar_avr_ug_zh.txt

-layout参数尽量保留原始排版,表格和代码片段不会糊成一行;grep -n输出行号,配合sed取上下文,比在阅读器里翻页快。抽出来的文本还可以丢进本地检索工具建索引,几个月后再遇到同一个报错,一条命令就能定位到当初记的页码。

第三步是维护一张自己的“现象—页码”对照表,只记自己撞过的坑,不抄目录。

我遇到的现象手册里的位置关键结论
列表文件没有源码行文件类型一节映象文件默认扩展名与列表冲突,改名
变量窗口看不到值C-SPY 调试器一节优化等级过高,调试配置单独一套
中断仿真不触发中断仿真一节需启用中断模拟并用宏注入
RAM 莫名其妙变少目录结构与文件一节查.map段汇总,只读数据加const

最后说个习惯。早年我遇到链接报错,第一反应是改代码试,改到第三次才想起来翻手册,结果那一条在 1.2.2 节的注意事项里写得清清楚楚。从那以后,凡是报错里带工具名——连接器、库管理器、调试器——我都会先花两分钟在这份 IAR 中文用户手册里搜一遍工具名加报错关键词,确认不是自己的用法问题,再动代码。这份手册不会教你写出更好的嵌入式程序,但它能保证你不把时间浪费在工具的脾气上。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询