99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

痞子衡
認(rèn)證:普通會員
所在專題目錄 查看專題
從文件角度看Cortex-M開發(fā)(1) - 源文件
從文件角度看Cortex-M開發(fā)(2) - 鏈接文件
從文件角度看Cortex-M開發(fā)(3) - 工程文件
從文件角度看Cortex-M開發(fā)(4) - 可重定向文件
從文件角度看Cortex-M開發(fā)(5) - 映射文件
從文件角度看Cortex-M開發(fā)(6) - 可執(zhí)行文件
作者動態(tài) 更多
一種多MCU分時復(fù)用Flash啟動的創(chuàng)新方法(下)
2星期前
一種多MCU分時復(fù)用Flash啟動的創(chuàng)新方法(上)
3星期前
RT10xx系列UART SDP能設(shè)置多高波特率?
06-06 09:51
有時候MCU片內(nèi)合封Flash就是個黑盒子!
05-15 13:52
有人說高性能MCU片內(nèi)合封Flash不可靠?
05-13 14:33

從文件角度看Cortex-M開發(fā)(3) - 工程文件

大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家講的是嵌入式開發(fā)里的project文件

前面兩節(jié)課里,痞子衡分別給大家介紹了嵌入式開發(fā)中的兩種典型input文件:源文件(.c/.h/.s)鏈接文件(.icf)。痞子衡要再次提問了,還有沒有input文件呢?答案確實是有,但這次真的是有且僅有了,本文要介紹的主角project文件也屬于半個input文件。為什么說是半個?因為project文件不僅包含開發(fā)者指定的input信息,還包含很多其他輔助調(diào)試的input/output信息,算是嵌入式開發(fā)中承前啟后的文件。而本文側(cè)重點在于project文件中與開發(fā)者應(yīng)用相關(guān)的input信息,僅當(dāng)?shù)玫搅诉@些input信息,再加上前面介紹的source和linker文件,那么你就已經(jīng)得到了application所有的信息,你可以用它們來可以生成無歧義的可執(zhí)行image binary。

隨著嵌入式軟件工程的發(fā)展,為了應(yīng)對日益復(fù)雜的需求,現(xiàn)代IDE的功能也越來越強(qiáng)大了,IDE版本更迭讓人應(yīng)接不暇,Keil MDK已然踏入5.0時代,IAR EWARM更是進(jìn)入了8.0時代,IDE各有千秋,但本文要講的內(nèi)容卻是每個IDE必須具有的基本功能,還是繼續(xù)以IAR EWARM為例開始今天的內(nèi)容:

一、標(biāo)準(zhǔn)IDE功能

在開始今天的主題之前,痞子衡覺得有必要先簡要給大家科普一下標(biāo)準(zhǔn)IDE應(yīng)該具有的功能。現(xiàn)代IDE基本都是由組件構(gòu)成,嵌入式開發(fā)中的每個階段都對應(yīng)著相應(yīng)的組件,由這些組件去實現(xiàn)各階段的需求。

1.1 IDE組件

標(biāo)準(zhǔn)嵌入式開發(fā)應(yīng)該至少包括以下6個階段,而IAR里對于每個階段都有1個或多個組件:

輸入(IAR Editor):編輯源文件代碼。

編譯(ICCARM、IASMARM):編譯源文件代碼生成可執(zhí)行二進(jìn)制機(jī)器碼。

分析(C-STAT、MISRA-C):編譯過程中檢查代碼中潛在的問題。

鏈接(ILINK):鏈接可執(zhí)行二進(jìn)制機(jī)器碼到指定ARM存儲空間地址。

下載(I-jet、flashloader):將鏈接好的可執(zhí)行二進(jìn)制機(jī)器碼下載進(jìn)芯片內(nèi)部非易失性存儲器。

調(diào)試(C-SPY、C-RUN):在線調(diào)試代碼在芯片中執(zhí)行情況。

project文件主要用來記錄整合上述6個階段的所有開發(fā)需求。

1.2 IDE文件類型

既然IDE有很多組件,那么同時也會存在不同類型的文件以存儲這些組件的所需要的信息。IAR里支持的文件擴(kuò)展類型非常多,痞子衡在這里僅列舉你所創(chuàng)建的工程根目錄下的與工程同名的擴(kuò)展文件,相信你一定會覺得眼熟。

.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

本文要講的內(nèi)容都包含在.ewp文件里,ewp文件記錄了開發(fā)者為應(yīng)用指定的不可缺少的input信息,沒有這些信息,application工程是不完整的。換句話說,如果你得到了application的所有source文件和linker文件,但沒有ewp文件的話,可能導(dǎo)致最終生成的image binary文件是不同的。

Note:更多IAR支持的擴(kuò)展文件類型請查閱IAR軟件安裝目錄下\IAR Systems\Embedded Workbench xxx\arm\doc\EWARM_IDEGuide.ENU.pdf文檔里的File types一節(jié)。

二、解析project(ewp)文件

前面痞子衡鋪墊了很多IDE/project基礎(chǔ)概念,該是直奔主題的時候了,本文主角ewp工程文件到底包含哪些開發(fā)者指定的input信息?痞子衡從下面3個方面為大家揭秘:

2.1 源文件組織

一個稍微復(fù)雜一點的嵌入式工程,應(yīng)用代碼行數(shù)應(yīng)該是以百行/千行為單位計算的(此處僅指的是由開發(fā)者自己創(chuàng)建的文件與代碼),我們在組織代碼的時候肯定不會只創(chuàng)建一個.c文件,單文件會導(dǎo)致代碼功能模塊結(jié)構(gòu)不清晰,不方便工程的管理與維護(hù)。

當(dāng)我們?yōu)楣こ虅?chuàng)建多個文件時,就會涉及到一個必然問題:引用路徑問題(所以路徑信息就是本文要說的第一個input信息)。當(dāng)源文件數(shù)目較多時,通常我們會創(chuàng)建不同文件夾把相同功能的源文件都放在一起,當(dāng)編譯器開始編譯.c源文件時會搜索include語句所包含的頭文件。熟悉C語言的朋友肯定清楚下面兩種不同include語句的用法:

#include <file.h>           // 引用編譯器類庫下的頭文件(IDE安裝路徑)
#include "file.h"           // 引用當(dāng)前工程下的頭文件(project路徑)

所以在ewp文件里會包含路徑信息,所有路徑都應(yīng)該列在Options->C/C++ Compiler->Preprocessor下有Additional include directories里,這個路徑既可以是當(dāng)前PC的絕對路徑,也可以是以ewp文件為基準(zhǔn)的相對路徑,為了保證工程可以在任意PC任意位置下正常編譯,推薦使用如下相對路徑方式列出所有路徑:

ewp當(dāng)前路徑:$PROJ_DIR$/
ewp下級路徑:$PROJ_DIR$/xxFolder/
ewp上級路徑:$PROJ_DIR$/../

說到路徑問題,痞子衡在這里順便給大家介紹一種經(jīng)典的嵌入式工程文件目錄組織方式:

\projectDir
           \doc                            --放置工程文檔

           \bsp                            --放置bsp(板級)相關(guān)的source file
                  \linker                    --工程linker文件
                  \src                       --板級相關(guān)的源文件(比如pinout,clock等)
                  \builds\xxBuild\.ewp       --工程ewp文件
                  .eww                       --工程workspace文件

           \src                            --放置bsp無關(guān)的source file
                  \platform                  --芯片頭文件及CMSIS文件
                  \drivers                   --芯片片內(nèi)外設(shè)driver
                  \include                   --要被所有source引用的頭文件
                  \startup                   --標(biāo)準(zhǔn)的startup code
                  \utilities                 --標(biāo)準(zhǔn)的通用函數(shù)
                  \middleware                --獨立的中間件
                  \components                --板級外設(shè)組件driver
                  \application               --當(dāng)前應(yīng)用主邏輯代碼

2.2 全局宏定義

經(jīng)常使用條件編譯的朋友肯定知道workspace文件與project文件的關(guān)系,一個項目通常只會有一個eww文件,但卻可能會有多個ewp文件,這是因為源代碼里常常會有條件編譯,我們有時候會給項目不同的配置從而編譯出不同的結(jié)果(速度優(yōu)先/面積優(yōu)先,特性控制...),這些配置就是由全局宏定義來實現(xiàn)的,打開Options->C/C++ Compiler->Preprocessor下的Defined symbols,在框內(nèi)寫入你需要定義的全局宏:

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

全局宏信息就是本文要說的第二個input信息,如果全局宏信息丟失,有時候工程編譯并不會報錯,因為編譯器在處理如下普遍用法里的條件編譯語句時會默認(rèn)未定義的宏為0,而在處理普遍用法里的條件編譯語句則會報錯,所以推薦大家使用第二種條件編譯用法來規(guī)避全局宏問題。

// 普遍用法
#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 編譯選項

編譯選項包含了編譯器所需要的所有信息,代碼需經(jīng)過編譯器編譯才能生成二進(jìn)制機(jī)器碼,不同的編譯器選項配置會生成不同的機(jī)器碼,那么需要指定哪些選項呢?打開project的Options選項卡,分別設(shè)置下表item:

Note:更多ewp文件中option解釋請查閱IAR軟件安裝目錄下\IAR Systems\Embedded Workbench xxx\arm\doc\EWARM_IDEGuide.ENU.pdf文檔里的General Options和Compiler Options倆小節(jié)。

編譯設(shè)置信息就是本文要說的第三個input信息,當(dāng)在project中組織好源文件并設(shè)置好正確的全局宏定義和編譯選項,那么恭喜你,你的application設(shè)計工作已經(jīng)基本完成了。

三、創(chuàng)建demo工程

為方便后續(xù)課程的進(jìn)行,本節(jié)課在最后順便創(chuàng)建一個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個系統(tǒng)中斷)
    \D\myProject\bsp\src\system_MKL25Z4.c   (僅做關(guān)閉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);
    }
}

番外一、幾個小技巧

又來到痞子衡番外時間了,細(xì)心的朋友看到上表有兩處標(biāo)藍(lán),是的沒錯,今天的番外內(nèi)容就是標(biāo)藍(lán)的項目有關(guān)。

技巧1:運(yùn)行于異構(gòu)雙核

目前嵌入式產(chǎn)品越來越復(fù)雜,對MCU的性能要求也越來越高,各大ARM廠商也在不斷推出性能越來越強(qiáng)勁的ARM MCU產(chǎn)品,超高主頻,雙核,四核MCU已經(jīng)不鮮見了。對于其中的一些異構(gòu)雙核MCU產(chǎn)品,有時在開發(fā)中會有這樣的需求:你有一份的middleware會被異構(gòu)雙核同時調(diào)用,而兩個不同內(nèi)核的指令集有可能是不一致的,怎么解決這個問題?有朋友會想到分別在每個核下面都編譯一份binary放置于存儲器不同位置,運(yùn)行時各自指向?qū)?yīng)的binary,這是一個辦法,但比較浪費(fèi)存儲空間,且有可能會搞混淆導(dǎo)致誤調(diào)用。有沒有更好的方法?

為了能做到Cortex-M軟件重用,ARM公司在設(shè)計Cortex-M處理器時為其賦予了處理器向下兼容軟件二進(jìn)制向上兼容特性。通俗的話來說就是在較低版本處理器上編譯的代碼可以在較高版本處理器上執(zhí)行。所以解決方法就是選用異構(gòu)雙核里較低版本的內(nèi)核在編譯middleware,這樣這份middleware可以同時被兩個核調(diào)用。

技巧2:生成PIC代碼

經(jīng)常和bootloader打交道的朋友肯定知道,代碼在經(jīng)過鏈接階段生成binary文件后,這個binary并不是可以放在任意位置的,必須放到linker文件指定的位置,如果位置沒有放正確,可能會導(dǎo)致執(zhí)行出錯。究其原因,是因為編譯器在匯編源代碼時因為一些策略并不總是將所有function都匯編成位置無關(guān)代碼。如果我們借助于IDE編譯選項將middleware匯編成PIC代碼,那么我們可以在工程中直接加入middleware的binary,然后借助linker的自定義section功能將其放置于任意某個位置,最后只要為這個middleware binary建立一個以binary首地址為基準(zhǔn)的函數(shù)指針地址列表即可無障礙調(diào)用這個middleware。

技巧3:引用.c文件

在項目開發(fā)中,我們在一個workspace下會創(chuàng)建多個project,常常是因為不同project需要包含不同的.c文件以完成不同的功能。那么能不能只創(chuàng)建一個project呢能實現(xiàn)不同功能呢?當(dāng)然可以!通常情況下我們在.c文件中只會用#include "xx.h"語句來引用.h頭文件,其實我們也同樣可以引用.c文件,比如這樣#include "xx.c",只是需要注意盡量不要在.h文件中引用.c文件(除非該.h只會被一個.c文件include)。看到這里的朋友如果腦洞再大一點,你甚至可以做到工程里只需要添加一個.c文件,而其他.c文件全部由添加進(jìn)工程的那個.c文件逐級(僅能單級)引用進(jìn)工程。

至此,嵌入式開發(fā)里的project文件痞子衡便介紹完畢了,掌聲在哪里~~~

聲明:本內(nèi)容為作者獨立觀點,不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 1
收藏 2
關(guān)注 41
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 强公把我次次高潮HD | 欧美视频亚洲视频 | 色综合激情一区二区三区 | 日本免费不卡一区二区 | 亚洲午夜福利在线观看老司机 | 九九热精品视频在线免费观看 | 日本一区二区三区精品福利视频 | 色多多官网 | 国产专区一区二区 | 人妻系列综合第一页 | 久久久久久一区国产精品 | 香蕉视频导航 | 日韩h网站 | 亚洲男女视频在线观看 | 日本xxxx裸体xxxx视频大全 | 日韩在线| 牲高潮99爽久久久久777 | 亚洲欭美日韩颜射在线二 | 91精品一区二区三区在线观看 | 人妻互换一二三区激情视频 | 久久日韩国产精品免费 | 免费网站看v片在线a | 成人做爰69片免费 | 噜噜爽av99| 欧美肥臀大屁股MAGNET | 91精品国产日韩一区二区三区 | 任你操精品视频 | 精品国产乱码久久久久久密桃99 | 国产特级黄色片 | 久久久久久久免费视频 | 超碰xx| 欧美性猛交XXXX黑人猛交 | 国产偷国产偷亚洲高清日韩 | 日本少妇高潮正在线播放 | 国产成人在线观看网站 | 欧美一级片一区 | 国产在线视精品在一区二区 | 亚洲av无码乱码在线观看富二代 | 免费看a | 青青草视频4 | 成人亚洲A片V一区二区三区色欲 |