天天看點

痞子衡嵌入式:ARM Cortex-M檔案那些事(3)- 工程檔案(.ewp)

project檔案不僅包含開發者指定的input資訊,還包含很多其他輔助調試的input/output資訊,算是嵌入式開發中承前啟後的檔案。而本文側重點在于project檔案中與開發者應用相關的input資訊,僅當得到了這些input資訊,再加上前面介紹的source和linker檔案,那麼你就已經得到了application所有的資訊,你可以用它們來可以生成無歧義的可執行image binary。

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是嵌入式開發裡的project檔案。

  前面兩節課裡,痞子衡分别給大家介紹了嵌入式開發中的兩種典型input檔案:源檔案(.c/.h/.s)、連結檔案(.icf)。痞子衡要再次提問了,還有沒有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基本都是由元件構成,嵌入式開發中的每個階段都對應着相應的元件,由這些元件去實作各階段的需求。

  标準嵌入式開發應該至少包括以下6個階段,而IAR裡對于每個階段都有1個或多個元件:

輸入(IAR Editor):編輯源檔案代碼。 編譯(ICCARM、IASMARM):編譯源檔案代碼生成可執行二進制機器碼。 分析(C-STAT、MISRA-C):編譯過程中檢查代碼中潛在的問題。 連結(ILINK):連結可執行二進制機器碼到指定ARM存儲空間位址。 下載下傳(I-jet、flashloader):将連結好的可執行二進制機器碼下載下傳進晶片内部非易失性存儲器。 調試(C-SPY、C-RUN):線上調試代碼在晶片中執行情況。

  project檔案主要用來記錄整合上述6個階段的所有開發需求。

  既然IDE有很多元件,那麼同時也會存在不同類型的檔案以存儲這些元件的所需要的資訊。IAR裡支援的檔案擴充類型非常多,痞子衡在這裡僅列舉你所建立的工程根目錄下的與工程同名的擴充檔案,相信你一定會覺得眼熟。

  本文要講的内容都包含在.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一節。

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

  一個稍微複雜一點的嵌入式工程,應用代碼行數應該是以百行/千行為機關計算的(此處僅指的是由開發者自己建立的檔案與代碼),我們在組織代碼的時候肯定不會隻建立一個.c檔案,單檔案會導緻代碼功能子產品結構不清晰,不友善工程的管理與維護。

  當我們為工程建立多個檔案時,就會涉及到一個必然問題:引用路徑問題(是以路徑資訊就是本文要說的第一個input資訊)。當源檔案數目較多時,通常我們會建立不同檔案夾把相同功能的源檔案都放在一起,當編譯器開始編譯.c源檔案時會搜尋include語句所包含的頭檔案。熟悉C語言的朋友肯定清楚下面兩種不同include語句的用法:

  是以在ewp檔案裡會包含路徑資訊,所有路徑都應該列在Options->C/C++ Compiler->Preprocessor下有Additional include directories裡,這個路徑既可以是目前PC的絕對路徑,也可以是以ewp檔案為基準的相對路徑,為了保證工程可以在任意PC任意位置下正常編譯,推薦使用如下相對路徑方式列出所有路徑:

  說到路徑問題,痞子衡在這裡順便給大家介紹一種經典的嵌入式工程檔案目錄組織方式:

  經常使用條件編譯的朋友肯定知道workspace檔案與project檔案的關系,一個項目通常隻會有一個eww檔案,但卻可能會有多個ewp檔案,這是因為源代碼裡常常會有條件編譯,我們有時候會給項目不同的配置進而編譯出不同的結果(速度優先/面積優先,特性控制...),這些配置就是由全局宏定義來實作的,打開Options->C/C++ Compiler->Preprocessor下的Defined symbols,在框内寫入你需要定義的全局宏:

  全局宏資訊就是本文要說的第二個input資訊,如果全局宏資訊丢失,有時候工程編譯并不會報錯,因為編譯器在處理如下普遍用法裡的條件編譯語句時會預設未定義的宏為0,而在處理普遍用法裡的條件編譯語句則會報錯,是以推薦大家使用第二種條件編譯用法來規避全局宏問題。

  編譯選項包含了編譯器所需要的所有資訊,代碼需經過編譯器編譯才能生成二進制機器碼,不同的編譯器選項配置會生成不同的機器碼,那麼需要指定哪些選項呢?打開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工程的資訊:

  又來到痞子衡番外時間了,細心的朋友看到上表有兩處标藍,是的沒錯,今天的番外内容就是标藍的項目有關。

  目前嵌入式産品越來越複雜,對MCU的性能要求也越來越高,各大ARM廠商也在不斷推出性能越來越強勁的ARM MCU産品,超高主頻,雙核,四核MCU已經不鮮見了。對于其中的一些異構雙核MCU産品,有時在開發中會有這樣的需求:你有一份的middleware會被異構雙核同時調用,而兩個不同核心的指令集有可能是不一緻的,怎麼解決這個問題?有朋友會想到分别在每個核下面都編譯一份binary放置于存儲器不同位置,運作時各自指向對應的binary,這是一個辦法,但比較浪費存儲空間,且有可能會搞混淆導緻誤調用。有沒有更好的方法?

  為了能做到Cortex-M軟體重用,ARM公司在設計Cortex-M處理器時為其賦予了處理器向下相容、軟體二進制向上相容特性。通俗的話來說就是在較低版本處理器上編譯的代碼可以在較高版本處理器上執行。是以解決方法就是選用異構雙核裡較低版本的核心在編譯middleware,這樣這份middleware可以同時被兩個核調用。

  經常和bootloader打交道的朋友肯定知道,代碼在經過連結階段生成binary檔案後,這個binary并不是可以放在任意位置的,必須放到linker檔案指定的位置,如果位置沒有放正确,可能會導緻執行出錯。究其原因,是因為編譯器在彙編源代碼時因為一些政策并不總是将所有function都彙編成位置無關代碼。如果我們借助于IDE編譯選項将middleware彙編成PIC代碼,那麼我們可以在工程中直接加入middleware的binary,然後借助linker的自定義section功能将其放置于任意某個位置,最後隻要為這個middleware binary建立一個以binary首位址為基準的函數指針位址清單即可無障礙調用這個middleware。

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

  至此,嵌入式開發裡的project檔案痞子衡便介紹完畢了,掌聲在哪裡~~~

文章會同時釋出到我的 部落格園首頁、CSDN首頁、微信公衆号 平台上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

痞子衡嵌入式:ARM Cortex-M檔案那些事(3)- 工程檔案(.ewp)

  最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。

痞子衡嵌入式:ARM Cortex-M檔案那些事(3)- 工程檔案(.ewp)
痞子衡嵌入式:ARM Cortex-M檔案那些事(3)- 工程檔案(.ewp)
痞子衡嵌入式:ARM Cortex-M檔案那些事(3)- 工程檔案(.ewp)

  衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。

  專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/

  與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]

  可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。

  關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。

  痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。

ARM