我是豹哥,我是豹哥



  大家好,我是豹哥,猎豹的豹,犀利哥的哥。后日豹哥给大家讲的是嵌入式开发里的project文件

  大家好,我是豹哥,猎豹的豹,犀利哥的哥。前几天豹哥给大家讲的是嵌入式开发里的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为例最先后日的内容:

  前边两节课里,豹哥分别给我们介绍了嵌入式开发中的两种典型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基本都是由组件构成,嵌入式开发中的每个阶段都对应着相应的组件,由那几个零件去完结各阶段的急需。

一、标准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.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里扶助的公文扩大项目至极多,豹哥在那边仅列举你所开创的工程根目录下的与工程同名的增加文件,相信你一定会认为驾驭。

.eww           // Workspace file
.ewp           // IAR Embedded Workbench project
.ewd           // Project settings for C-SPY
.ewt           // Project settings for C-STAT and C-RUN</td>
.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一节。

1.2 IDE文件类型

  既然IDE有那个零件,那么与此同时也会存在不一致门类的文书以存储那么些零部件的所急需的音讯。IAR里支持的文本增添项目卓殊多,豹哥在此地仅列举你所开创的工程根目录下的与工程同名的壮大文件,相信您肯定会以为通晓。

.eww           // Workspace file
.ewp           // IAR Embedded Workbench project
.ewd           // Project settings for C-SPY
.ewt           // Project settings for C-STAT and C-RUN</td>
.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新闻?豹哥从上面3个地点为大家揭开:

二、解析project(ewp)文件

  后面豹哥铺垫了累累IDE/project基础概念,该是直奔主旨的时候了,本文主演ewp工程文件到底包含哪些开发者指定的input新闻?豹哥从上边3个方面为大家揭秘:

2.1 源文件协会

  一个多少复杂一点的嵌入式工程,应用代码行数应该是以百行/千行为单位总计的(此处仅指的是由开发者自己创制的文书与代码),大家在集体代码的时候肯定不会只开创一个.c文件,单文件会造成代码功用模块结构不清晰,不便利工程的田间管理与保安。
  当我们为工程成立七个文件时,就会波及到一个一定问题:引用路径问题(所以路径音信就是本文要说的首个input新闻)。当源文件数量较多时,平时大家会创制不相同文件夹把相同效果的源文件都位居一起,当编译器起先编译.c源文件时会搜索include语句所包含的头文件。熟知C语言的意中人肯定晓得上面二种差别include语句的用法:

#include <file.h>           // 引用编译器类库下的头文件(IDE安装路径)
#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                 --标准的通用函数
                  \middleware                --独立的中间件
                  \components                --板级外设组件driver
                  \application               --当前应用主逻辑代码

2.1 源文件协会

  一个不怎么复杂一点的嵌入式工程,应用代码行数应该是以百行/千行为单位总计的(此处仅指的是由开发者自己创造的公文与代码),我们在社团代码的时候势必不会只开创一个.c文件,单文件会促成代码功用模块结构不明显,不便于工程的军事管制与尊敬。
  当大家为工程创制多少个文件时,就会波及到一个必将问题:引用路径问题(所以路径音讯就是本文要说的首先个input音讯)。当源文件数量较多时,平时大家会制造分歧文件夹把相同效果的源文件都位于一起,当编译器开头编译.c源文件时会搜索include语句所包蕴的头文件。熟练C语言的心上人一定晓得上边二种分裂include语句的用法:

#include <file.h>           // 引用编译器类库下的头文件(IDE安装路径)
#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                 --标准的通用函数
                  \middleware                --独立的中间件
                  \components                --板级外设组件driver
                  \application               --当前应用主逻辑代码

2.2 全局宏定义

  常常利用规范编译的恋人一定明白workspace文件与project文件的涉嫌,一个种类一般只会有一个eww文件,但却可能会有多个ewp文件,这是因为源代码里平日会有规范编译,我们有时会给品种分裂的布局从而编译出差距的结果(速度优先/面积优先,特性控制…),这一个布置就是由全局宏定义来已毕的,打开Options->C/C++
Compiler->Preprocessor下的Defined
symbols,在框内写入你必要定义的全局宏:

MACRO1            // 等价于源文件里的#define MACRO1 (1)
MACRO2=2          // 等价于源文件里的#define MACRO2 (2)

  全局宏音讯就是本文要说的第三个input音讯,借使全局宏新闻丢失,有时候工程编译并不会报错,因为编译器在拍卖如下普遍用法里的尺度编译语句时会默许未定义的宏为0,而在拍卖推荐用法里的基准编译语句则会报错,所以推举大家使用第三种标准编译用法来逃避全局宏问题。

// 普遍用法
#if MACRO
    // your code block 1
#else
    // your code block 2
#endif

// 推荐用法
#if !defined(MACRO)
    #error "No valid MACRO defined!"
#elif (MACRO == 1)
    // your code block 1
#else
    // your code block 2
#endif

2.2 全局宏定义

  日常利用规范编译的爱人一定精晓workspace文件与project文件的涉及,一个门类一般只会有一个eww文件,但却可能会有多少个ewp文件,那是因为源代码里不时会有原则编译,我们有时会给品种不一致的陈设从而编译出差距的结果(速度优先/面积优先,特性控制…),那么些配置就是由全局宏定义来完毕的,打开Options->C/C++
Compiler->Preprocessor下的Defined
symbols,在框内写入你须要定义的全局宏:

MACRO1            // 等价于源文件里的#define MACRO1 (1)
MACRO2=2          // 等价于源文件里的#define MACRO2 (2)

  全局宏新闻就是本文要说的第四个input信息,若是全局宏信息丢失,有时候工程编译并不会报错,因为编译器在处理如下普遍用法里的规则编译语句时会默许未定义的宏为0,而在处理推荐用法里的条件编译语句则会报错,所以推举大家利用第三种标准编译用法来躲避全局宏问题。

// 普遍用法
#if MACRO
    // your code block 1
#else
    // your code block 2
#endif

// 推荐用法
#if !defined(MACRO)
    #error "No valid MACRO defined!"
#elif (MACRO == 1)
    // your code block 1
#else
    // your code block 2
#endif

2.3 编译选项

  编译选项包蕴了编译器所须求的有着新闻,代码需通过编译器编译才能生成二进制机器码,差其余编译器选项配置会转变不相同的机器码,那么要求指定哪些选项呢?打开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俩小节。

  编译设置音信就是本文要说的第二个input音信,当在project中集团好源文件并安装好正确的大局宏定义和编译选项,那么恭喜你,你的application设计工作已经主导已毕了。

2.3 编译选项

  编译选项包涵了编译器所急需的具有音信,代码需通过编译器编译才能生成二进制机器码,差别的编译器选项配置会转变差距的机器码,那么需求指定哪些选项呢?打开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俩小节。

  编译设置音讯就是本文要说的第多少个input信息,当在project中集体好源文件并安装好正确的全局宏定义和编译选项,那么恭喜你,你的application设计工作早已基本形成了。

三、创建demo工程

  为便于后续课程的开展,本节课在结尾顺便创制一个demo工程,以下是demo工程的信息:

IDE:        IAR EWARM v8.11.2
Device:     NXP MKL25Z128VLH4
project layout:   
    \D\myProject\bsp\builds\demo\demo.ewp
    \D\myProject\bsp\linker\iar\KL25Z128xxx4_flash.icf
    \D\myProject\bsp\src\startup_MKL25Z4.s   (仅保留前16个系统中断)
    \D\myProject\bsp\src\system_MKL25Z4.c   (仅做关闭WDOG操作)
    \D\myProject\bsp\src\system_MKL25Z4.h
    \D\myProject\bsp\helloArm.eww
    \D\myProject\src\platfrom\CMSIS
    \D\myProject\src\platfrom\devices\MKL25Z4
    \D\myProject\src\startup\reset.s
    \D\myProject\src\startup\startup.c
    \D\myProject\src\startup\startup.h
    \D\myProject\src\application\main.c
    \D\myProject\src\application\task.c
    \D\myProject\src\application\task.h

// main.c
//////////////////////////////////////////////////////////
#include "task.h"
const uint32_t s_constant = 0x7f;
int main(void)
{
    uint32_t l_variable = 0x7f;
    if (s_constant == l_variable)
    {
        normal_task();
        ram_task();
        heap_task();
    }
    while (1);
}

// task.c
//////////////////////////////////////////////////////////
#include "task.h"
static    uint32_t s_variable0;
__no_init uint32_t n_variable1;
static    uint32_t s_variable2 = 0x5a;
static uint8_t s_array[16];
void normal_task(void)
{
    s_variable0 *= 2;
}
__ramfunc void ram_task(void)
{
    n_variable1++;
}
void heap_task(void)
{
    uint8_t *heap = (uint8_t *)malloc(16 * sizeof(uint8_t));
    if (heap != NULL)
    {
        memset(heap, 0xa5+s_variable2, 16);
        memcpy(s_array, heap, 16);
        s_variable0 = (uint32_t)heap;
        free(heap);
    }
}

三、创建demo工程

  为便宜后续课程的举办,本节课在结尾顺便创制一个demo工程,以下是demo工程的信息:

IDE:        IAR EWARM v8.11.2
Device:     NXP MKL25Z128VLH4
project layout:   
    \D\myProject\bsp\builds\demo\demo.ewp
    \D\myProject\bsp\linker\iar\KL25Z128xxx4_flash.icf
    \D\myProject\bsp\src\startup_MKL25Z4.s   (仅保留前16个系统中断)
    \D\myProject\bsp\src\system_MKL25Z4.c   (仅做关闭WDOG操作)
    \D\myProject\bsp\src\system_MKL25Z4.h
    \D\myProject\bsp\helloArm.eww
    \D\myProject\src\platfrom\CMSIS
    \D\myProject\src\platfrom\devices\MKL25Z4
    \D\myProject\src\startup\reset.s
    \D\myProject\src\startup\startup.c
    \D\myProject\src\startup\startup.h
    \D\myProject\src\application\main.c
    \D\myProject\src\application\task.c
    \D\myProject\src\application\task.h

// main.c
//////////////////////////////////////////////////////////
#include "task.h"
const uint32_t s_constant = 0x7f;
int main(void)
{
    uint32_t l_variable = 0x7f;
    if (s_constant == l_variable)
    {
        normal_task();
        ram_task();
        heap_task();
    }
    while (1);
}

// task.c
//////////////////////////////////////////////////////////
#include "task.h"
static    uint32_t s_variable0;
__no_init uint32_t n_variable1;
static    uint32_t s_variable2 = 0x5a;
static uint8_t s_array[16];
void normal_task(void)
{
    s_variable0 *= 2;
}
__ramfunc void ram_task(void)
{
    n_variable1++;
}
void heap_task(void)
{
    uint8_t *heap = (uint8_t *)malloc(16 * sizeof(uint8_t));
    if (heap != NULL)
    {
        memset(heap, 0xa5+s_variable2, 16);
        memcpy(s_array, heap, 16);
        s_variable0 = (uint32_t)heap;
        free(heap);
    }
}

番外一、多少个小技巧

  又赶到豹哥番外时间了,细心的恋人看出上表有两处标蓝,是的科学,明日的番外内容就是标蓝的品种有关。

番外一、多少个小技巧

  又来到豹哥番外时间了,细心的情侣看出上表有两处标蓝,是的科学,今日的番外内容就是标蓝的体系有关。

技巧1:运行于异构双核

  近期嵌入式产品尤其复杂,对MCU的性质须求也愈发高,各大ARM厂商也在持续推出性能进一步强大的ARM
MCU产品,超高主频,双核,四核MCU已经不鲜见了。对于其中的片段异构双核MCU产品,有时在付出中会有那样的必要:你有一份的middleware会被异构双核同时调用,而七个分裂基础的吩咐集有可能是区其余,怎么化解那些问题?有情侣会想到分别在各种核上面都编译一份binary放置于存储器不一致义务,运行时分别指向对应的binary,那是一个措施,但正如浪费存储空间,且有可能会搞混淆导致误调用。有没有更好的点子?
  为了能成功Cortex-M软件重用,ARM公司在陈设Cortex-M处理器时为其予以了处理器向下包容软件二进制向上包容特征。通俗的话来说就是在较低版本处理器上编译的代码可以在较高版本处理器上执行。所以解决格局就是选择异构双核里较低版本的内核在编译middleware,那样这份middleware可以而且被七个核调用。

技能1:运行于异构双核

  近期嵌入式产品越发复杂,对MCU的习性需求也更加高,各大ARM厂商也在不停推出性能更是强大的ARM
MCU产品,超高主频,双核,四核MCU已经不鲜见了。对于其中的有的异构双核MCU产品,有时在付出中会有这么的急需:你有一份的middleware会被异构双核同时调用,而四个分歧基础的命令集有可能是不一致等的,怎么解决这么些问题?有心上人会想到分别在每个核下边都编译一份binary停放于存储器不一致地方,运行时分别指向对应的binary,那是一个方法,但正如浪费存储空间,且有可能会搞混淆导致误调用。有没有更好的法门?
  为了能成就Cortex-M软件重用,ARM公司在规划Cortex-M处理器时为其给予了电脑向下包容软件二进制向上包容特性。通俗的话来说就是在较低版本处理器上编译的代码可以在较高版本处理器上举办。所以解决办法就是拔取异构双核里较低版本的水源在编译middleware,那样那份middleware可以同时被多个核调用。

技巧2:生成PIC代码

  平日和bootloader打交道的心上人肯定精晓,代码在通过链接阶段生成binary文件后,那一个binary并不是足以放在任意地方的,必须置于linker文件指定的岗位,假使地点并未放正确,可能会导致执行出错。究其原因,是因为编译器在汇编源代码时因为有些策略并不一而再将具备function都汇编成地点无关代码。假如大家借助IDE编译选项将middleware汇编成PIC代码,那么大家可以在工程中直接参加middleware的binary,然后借助linker的自定义section成效将其放置于自由某个地点,最终只要为这么些middleware
binary建立一个以binary首地址为条件的函数指针地址列表即可无障碍调用那一个middleware。

技巧2:生成PIC代码

  平常和bootloader打交道的情侣一定晓得,代码在通过链接阶段生成binary文件后,那几个binary并不是足以放在任意地方的,必须置于linker文件指定的岗位,假设地方并未放正确,可能会造成执行出错。究其原因,是因为编译器在汇编源代码时因为有些策略并不总是将有所function都汇编成地点非亲非故代码。若是大家借助IDE编译选项将middleware汇编成PIC代码,那么大家可以在工程中一向插手middleware的binary,然后借助linker的自定义section成效将其放置于自由某个地方,最终只要为那一个middleware
binary建立一个以binary首地址为条件的函数指针地址列表即可无障碍调用这几个middleware。

技巧3:引用.c文件

  在档次开销中,大家在一个workspace下会创设多少个project,平时是因为不同project要求包罗分化的.c文件以完毕不相同的出力。那么能或不能够只创建一个project呢能落到实处不一致效能吗?当然可以!平常情况下我们在.c文件中只会用#include
“xx.h”语句来引用.h头文件,其实大家也同样可以引用.c文件,比如这样#include
“xx.c”,只是需求留意尽量不要在.h文件中引用.c文件(除非该.h只会被一个.c文件include)。看到此间的情人就算脑洞再大一点,你甚至足以成功工程里只要求添加一个.c文件,而其余.c文件全体由添加进工程的丰硕.c文件逐级(仅能单级)引用进工程。

  至此,嵌入式开发里的project文件豹哥便介绍已毕了,掌声在何地~~~

技巧3:引用.c文件

  在类型支付中,我们在一个workspace下会创立多少个project,平常是因为差别project要求蕴涵分化的.c文件以成就不一样的成效。那么能无法只创制一个project呢能完成差距功能吗?当然可以!经常状态下大家在.c文件中只会用#include
“xx.h”语句来引用.h头文件,其实大家也一律可以引用.c文件,比如这样#include
“xx.c”,只是必要留意尽量不要在.h文件中引用.c文件(除非该.h只会被一个.c文件include)。看到此间的爱人倘若脑洞再大一点,你甚至足以成功工程里只要求添加一个.c文件,而任何.c文件全体由添加进工程的更加.c文件逐级(仅能单级)引用进工程。

  至此,嵌入式开发里的project文件豹哥便介绍达成了,掌声在哪儿~~~

相关文章