大家好,我是豹哥,猎豹的豹,犀利哥的哥。今天豹哥给大家讲的是嵌入式开发里的project文件。
前面两节课里,豹哥分别给大家介绍了嵌入式开发中的两种典型input文件:source文件、linker文件。豹哥要再次提问了,还有没有input文件呢?答案确实是有,但这次真的是有且仅有了,本文要介绍的主角project文件也属于半个input文件。为什么说是半个?因为project文件不仅包含开发者指定的input信息,还包含很多其他辅助调试的input/output信息,算是嵌入式开发中承前启后的文件。而本文侧重点在于project文件中与开发者应用相关的input信息,仅当得到了这些input信息,再加上前面介绍的source和linker文件,那么你就已经得到了application所有的信息,你可以用它们来可以生成无歧义的可执行image binary。
随着嵌入式软件工程的发展,为了应对日益复杂的需求,现代IDE的功能也越来越强大了,IDE版本更迭让人应接不暇,Keil MDK已然踏入5.0时代,IAR EWARM更是进入了8.0时代,IDE各有千秋,但本文要讲的内容却是每个IDE必须具有的基本功能,还是继续以IAR EWARM为例开始今天的内容:
一、标准IDE功能
在开始今天的主题之前,豹哥觉得有必要先简要给大家科普一下标准IDE应该具有的功能。现代IDE基本都是由组件构成,嵌入式开发中的每个阶段都对应着相应的组件,由这些组件去实现各阶段的需求。
1.1 IDE组件
标准嵌入式开发应该至少包括以下6个阶段,而IAR里对于每个阶段都有1个或多个组件:
- 输入(IAR Editor):编辑源文件代码。
- 编译(ICCARM、IASMARM):编译源文件代码生成可执行二进制机器码。
- 分析(C-STAT、MISRA-C):编译过程中检查代码中潜在的问题。
- 链接(ILINK):链接可执行二进制机器码到指定ARM存储空间地址。
- 下载(I-jet、flashloader):将链接好的可执行二进制机器码下载进芯片内部非易失性存储器。
- 调试(C-SPY、C-RUN):在线调试代码在芯片中执行情况。
project文件主要用来记录整合上述6个阶段的所有开发需求。
1.2 IDE文件类型
既然IDE有很多组件,那么同时也会存在不同类型的文件以存储这些组件的所需要的信息。IAR里支持的文件扩展类型非常多,豹哥在这里仅列举你所创建的工程根目录下的与工程同名的扩展文件,相信你一定会觉得眼熟。
Ext: Type of file:
.eww Workspace file
.ewp IAR Embedded Workbench project
.ewd Project settings for C-SPY
.ewt Project settings for C-STAT and C-RUN
.dep Dependency information
本文要讲的内容都包含在.ewp文件里,ewp文件记录了开发者为应用指定的不可缺少的input信息,没有这些信息,application工程是不完整的。换句话说,如果你得到了application的所有source文件和linker文件,但没有ewp文件的话,可能导致最终生成的image binary文件是不同的。
Note:更多IAR支持的扩展文件类型请查阅IAR软件安装目录下\IAR Systems\Embedded Workbench xxx\arm\doc\EWARM_IDEGuide.ENU.pdf文档里的File types一节。
二、解析project(ewp)文件
前面豹哥铺垫了很多IDE/project基础概念,该是直奔主题的时候了,本文主角ewp工程文件到底包含哪些开发者指定的input信息?豹哥从下面2个方面为大家揭秘:
2.1 源文件组织
一个稍微复杂一点的嵌入式工程,应用代码行数应该是以百行/千行为单位计算的(此处仅指的是由开发者自己创建的文件与代码),我们在组织代码的时候肯定不会只创建一个.c文件,单文件会导致代码功能模块结构不清晰,不方便工程的管理与维护。
当我们为工程创建多个文件时,就会涉及到一个必然问题:路径问题。当源文件数目较多时,通常我们会创建不同文件夹把相同功能的源文件都放在一起,当编译器开始编译.c源文件时会搜索include语句所包含的头文件。熟悉C语言的朋友肯定清楚下面两种不同include语句的用法:
#include <file.h> // 引用编译器类库下的头文件(系统路径)
#include "file.h" // 引用当前工程下的头文件(project路径)
所以在ewp文件里会包含路径信息,所有路径都应该列在Options->C/C++ Compiler->Preprocessor下有Additional include directories里,这个路径既可以是当前PC的绝对路径,也可以是以ewp文件为基准的相对路径,为了保证工程可以在任意PC任意位置下正常编译,推荐使用如下相对路径方式列出所有路径:
ewp当前路径:$PROJ_DIR$/
ewp下级路径:$PROJ_DIR$/xxFolder/
ewp上级路径:$PROJ_DIR$/../
说到路径问题,豹哥在这里顺便给大家介绍一种经典的嵌入式工程文件目录组织方式:
\projectDir
\doc --放置工程文档
\bsp --放置bsp相关的source file
\linker --工程linker文件
\src --工程板级相关的源文件(比如pinout,clock等)
\builds\xxBuild\.ewp --工程ewp文件
.eww --工程workspace文件
\src --放置bsp无关的source file
\platform --芯片头文件及CMSIS文件
\drivers --芯片各模块driver
\include --要被所有source引用的头文件
\startup --标准的startup code
\utilities --标准的通用函数
\components --应用组件
\application --应用代码
2.2 编译选项
编译选项包含了编译器所需要的所有信息,代码需经过编译器编译才能生成二进制机器码,不同的编译器选项配置会生成不同的机器码,那么需要指定哪些选项呢?打开project的Options选项卡,分别设置下表item:
Position | Item | Description |
---|---|---|
General Options->Target-> | Processor variant->Core | 指定ARM内核版本 |
Endian mode | 指定内核大小端模式 | |
Floating point settings->FPU | 指定内核支持的FPU版本 | |
General Options->Library Configuration-> | Library | 选择C/C++动态链接库版本 |
General Options->Library Option 2-> | Heap selection | 选择HEAP实现版本 |
C/C++ Compiler-> | Language 1->Language | 指定编程语言类型 |
Language 1->C dialect | 指定C语言标准 | |
Language 1->Language conformance | 选择对标准C/C++的遵循程度 | |
Language 2->Plain ‘char‘ is | 选择对char的符号性默认处理方法 | |
Language 2->Floating-point semantics | 选择对浮点数的处理遵循C标准的程度 | |
Code->Process mode | 指定内核指令集模式 | |
Code->Position-independence | 选择要生成位置无关代码的对象 | |
Optimizations->Level | 选择优化等级 |
Note:更多ewp文件中option解释请查阅IAR软件安装目录下\IAR Systems\Embedded Workbench xxx\arm\doc\EWARM_IDEGuide.ENU.pdf文档里的General Options和Compiler Options俩小节。
当在project中组织好源文件并设置好正确的编译选项,那么恭喜你,你的application设计工作已经基本完成了。
番外一、几个小技巧
小技巧待续
至此,嵌入式开发里的project文件豹哥便介绍完毕了,掌声在哪里~~~