單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網(wǎng)單片機
W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內置MAC以及PHY,擁有獨立的32KB以太網(wǎng)收發(fā)緩存,可供8個獨立硬件socket使用。如此配置,真正實現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。
在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN100和QFN68。
W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復雜工控場景設計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設資源,能夠輕松應對工業(yè)控制中多樣化的連接需求,無論是與各類傳感器、執(zhí)行器的通信,還是對復雜工業(yè)協(xié)議的支持,都能游刃有余,成為復雜工控領域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網(wǎng)關模組等場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網(wǎng)站或者私信獲取。
此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網(wǎng)絡通信安全再添保障。
為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32L這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線,就能輕松實現(xiàn)調試、下載以及串口打印日志等功能。開發(fā)板將所有外設全部引出,拓展功能也大幅提升,便于開發(fā)者全面評估芯片性能。
若您想獲取芯片和開發(fā)板的更多詳細信息,包括產品特性、技術參數(shù)以及價格等,歡迎訪問官方網(wǎng)頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。
第三十章 MDK的編譯過程及文件類型
相信您已經非常熟練地使用MDK創(chuàng)建應用程序了,平時使用MDK編寫源代碼,然后編譯生成機器碼,再把機器碼下載到STM32芯片上運行, 但是這個編譯、下載的過程MDK究竟做了什么工作?它編譯后生成的各種文件又有什么作用?本章節(jié)將對這些過程進行講解, 了解編譯及下載過程有助于理解芯片的工作原理,這些知識對制作IAP(bootloader)以及讀寫控制器內部FLASH的應用時非常重要。
1 編譯過程
首先我們簡單了解下MDK的編譯過程,它與其它編譯器的工作過程是類似的, 該過程見下圖:
編譯過程生成的不同文件將在后面的小節(jié)詳細說明,此處先抓住主要流程來理解。
(1) 編譯,MDK軟件使用的編譯器是armcc和armasm, 它們根據(jù)每個c/c++和匯編源文件編譯成對應的以“.o”為后綴名的對象文件(Object Code,也稱目標文件), 其內容主要是從源文件編譯得到的機器碼,包含了代碼、數(shù)據(jù)以及調試使用的信息;
(2) 鏈接, 鏈接器armlink把各個.o文件及庫文件鏈接成一個映像文件“.axf”或“.elf”;
(3) 格式轉換,一般來說Windows或Linux系統(tǒng)使用鏈接器直接生成可執(zhí)行映像文件elf后,內核根據(jù)該文件的信息加載后, 就可以運行程序了,但在單片機平臺上,需要把該文件的內容加載到芯片上, 所以還需要對鏈接器生成的elf映像文件利用格式轉換器fromelf轉換成“.bin”或“.hex”文件,交給下載器下載到芯片的FLASH或ROM中。
2 程序的組成、存儲與運行
2.1 CODE、RO、RW、ZI Data域及堆棧空間
在工程的編譯提示輸出信息中有一個語句“Program Size:Code=xx RO-data=xx RW-data=xx ZI-data=xx”, 它說明了程序各個域的大小,編譯后,應用程序中所有具有同一性質的數(shù)據(jù)(包括代碼)被歸到一個域,程序在存儲或運行的時候, 不同的域會呈現(xiàn)不同的狀態(tài),這些域的意義如下:
Code:即代碼域,它指的是編譯器生成的機器指令,這些內容被存儲到ROM區(qū)。
RO-data:Read Only data,即只讀數(shù)據(jù)域,它指程序中用到的只讀數(shù)據(jù),這些數(shù)據(jù)被存儲在ROM區(qū),因而程序不能修改其內容。 例如C語言中const關鍵字定義的變量就是典型的RO-data。
RW-data:Read Write data,即可讀寫數(shù)據(jù)域,它指初始化為“非0值”的可讀寫數(shù)據(jù),程序剛運行時,這些數(shù)據(jù)具有非0的初始值, 且運行的時候它們會常駐在RAM區(qū),因而應用程序可以修改其內容。例如C語言中使用定義的全局變量,且定義時賦予“非0值”給該變量進行初始化。
ZI-data:Zero Initialie data,即0初始化數(shù)據(jù),它指初始化為“0值”的可讀寫數(shù)據(jù)域, 它與RW-data的區(qū)別是程序剛運行時這些數(shù)據(jù)初始值全都為0, 而后續(xù)運行過程與RW-data的性質一樣,它們也常駐在RAM區(qū),因而應用程序可以更改其內容。例如C語言中使用定義的全局變量, 且定義時賦予“0值”給該變量進行初始化(若定義該變量時沒有賦予初始值,編譯器會把它當ZI-data來對待,初始化為0);
ZI-data的棧空間(Stack)及堆空間(Heap):在C語言中,函數(shù)內部定義的局部變量屬于棧空間,進入函數(shù)的時候從向棧空間申請內存給局部變量, 退出時釋放局部變量,歸還內存空間。而使用malloc動態(tài)分配的變量屬于堆空間。在程序中的棧空間和堆空間都是屬于ZI-data區(qū)域的, 這些空間都會被初始值化為0值。編譯器給出的ZI-data占用的空間值中包含了堆棧的大小(經實際測試,若程序中完全沒有使用malloc動態(tài)申請堆空間, 編譯器會優(yōu)化,不把堆空間計算在內)。
綜上所述,以程序的組成構件為例,它們所屬的區(qū)域類別見下表:
程序組件 | 所屬類別 |
機器代碼指令 | Code |
常量 | RO-data |
初值非 0 的全局變量 | RW-data |
初值為 0 的全局變量 | ZI-data |
局部變量 | ZI-data 棧空間 |
使用 malloc 動態(tài)分配的空間 | ZI-data 堆空間 |
2.2 程序的存儲與運行
RW-data和ZI-data它們僅僅是初始值不一樣而已,為什么編譯器非要把它們區(qū)分開?這就涉及到程序的存儲狀態(tài)了,應用程序具有靜止狀態(tài)和運行狀態(tài)。 靜止態(tài)的程序被存儲在非易失存儲器中,如STM32的內部FLASH,因而系統(tǒng)掉電后也能正常保存。但是當程序在運行狀態(tài)的時候,程序常常需要修改一些暫存數(shù)據(jù), 由于運行速度的要求,這些數(shù)據(jù)往往存放在內存中(RAM),掉電后這些數(shù)據(jù)會丟失。因此,程序在靜止與運行的時候它在存儲器中的表現(xiàn)是不一樣的, 見下圖:
圖中的左側是應用程序的存儲狀態(tài),右側是運行狀態(tài),而上方是RAM存儲器區(qū)域,下方是ROM存儲器區(qū)域。
程序在存儲狀態(tài)時,RO節(jié)(RO section)及RW節(jié)都被保存在ROM區(qū)。當程序開始運行時,內核直接從ROM中讀取代碼,并且在執(zhí)行主體代碼前, 會先執(zhí)行一段加載代碼,它把RW節(jié)數(shù)據(jù)從ROM復制到RAM, 并且在RAM加入ZI節(jié),ZI節(jié)的數(shù)據(jù)都被初始化為0。加載完后RAM區(qū)準備完畢,正式開始執(zhí)行主體程序。
編譯生成的RW-data的數(shù)據(jù)屬于圖中的RW節(jié),ZI-data的數(shù)據(jù)屬于圖中的ZI節(jié)。是否需要掉電保存,這就是把RW-data與ZI-data區(qū)別開來的原因, 因為在RAM創(chuàng)建數(shù)據(jù)的時候,默認值為0,但如果有的數(shù)據(jù)要求初值非0,那就需要使用ROM記錄該初始值,運行時再復制到RAM。
STM32的RO區(qū)域不需要加載到SRAM,內核直接從FLASH讀取指令運行。計算機系統(tǒng)的應用程序運行過程很類似,不過計算機系統(tǒng)的程序在存儲狀態(tài)時位于硬盤, 執(zhí)行的時候甚至會把上述的RO區(qū)域(代碼、只讀數(shù)據(jù))加載到內存,加快運行速度,還有虛擬內存管理單元(MMU)輔助加載數(shù)據(jù), 使得可以運行比物理內存還大的應用程序。而STM32沒有MMU,所以無法支持Linux和Windows系統(tǒng)。
當程序存儲到STM32芯片的內部FLASH時(即ROM區(qū)),它占用的空間是Code、RO-data及RW-data的總和,所以如果這些內容比STM32芯片的FLASH空間大, 程序就無法被正常保存了。當程序在執(zhí)行的時候,需要占用內部SRAM空間(即RAM區(qū)),占用的空間包括RW-data和ZI-data。 應用程序在各個狀態(tài)時各區(qū)域的組成見下表:
程序狀態(tài)與區(qū)域 | 組成 |
程序執(zhí)行時的只讀區(qū)域 (RO) | Code + RO data |
程序執(zhí)行時的可讀寫區(qū)域 (RW) | RW data + ZI data |
程序存儲時占用的 ROM 區(qū) | Code + RO data + RW data |
在MDK中,我們建立的工程一般會選擇芯片型號,選擇后就有確定的FLASH及SRAM大小,若代碼超出了芯片的存儲器的極限, 編譯器會提示錯誤,這時就需要裁剪程序了,裁剪時可針對超出的區(qū)域來優(yōu)化。
2.3編譯工具鏈
在前面編譯過程中,MDK調用了各種編譯工具,平時我們直接配置MDK,不需要學習如何使用它們,但了解它們是非常有好處的。例如, 若希望使用MDK編譯生成bin文件的,需要在MDK中輸入指令控制fromelf工具;在本章后面講解AXF及O文件的時候,需要利用fromelf工具查看其文件信息, 這都是無法直接通過MDK做到的。關于這些工具鏈的說明,在MDK的幫助手冊《ARM Development Tools》都有詳細講解, 點擊MDK界面的“help->uVision Help”菜單可打開該文件。
2.3.1armcc
armcc用于把c/c++文件編譯成ARM指令代碼,編譯后會輸出ELF格式的O文件(對象、目標文件),在命令行中輸入“armcc”回車可調用該工具, 它會打印幫助說明,見下圖,armcc的幫助提示:
幫助提示中分三部分,第一部分是armcc版本信息,第二部分是命令的用法,第三部分是主要命令選項。
根據(jù)命令用法: armcc [options] file1 file2 …filen , 在[option]位置可輸入下面的“–arm”、“–cpu list”選項, 若選項帶文件輸入,則把文件名填充在file1 file2…的位置,這些文件一般是c/c++文件。
例如根據(jù)它的幫助說明,“–cpu list”可列出編譯器支持的所有cpu,我們在命令行中輸入“armcc –cpu list”, 可查看圖中的cpu列表:
打開MDK的Options for Targe->c/c++菜單,可看到MDK對編譯器的控制命令, 見下圖,MDK的ARMCC編譯選項:
從該圖中的命令可看到,它調用了-c、-cpu –D –g –O1等編譯選項,當我們修改MDK的編譯配置時,可看到該控制命令也會有相應的變化。 然而我們無法在該編譯選項框中輸入命令,只能通過MDK提供的選項修改。
了解這些,我們就可以查詢具體的MDK編譯選項的具體信息了,如c/c++選項中的“Optimization:Leve 1(-O1)”是什么功能呢? 首先可了解到它是“-O”命令,命令后還帶個數(shù)字,查看MDK的幫助手冊,在armcc編譯器說明章節(jié), 可詳細了解,如下圖,編譯器選項說明:
利用MDK,我們一般不需要自己調用armcc工具,但經過這樣的過程我們就會對MDK有更深入的認識,面對它的各種編譯選項,就不會那么頭疼了。
2.3.2 armasm
armasm是匯編器,它把匯編文件編譯成O文件。與armcc類似, MDK對armasm的調用選項可在“Option for Target->Asm”頁面進行配置, 見下圖,armasm與MDK的編譯選項:
2.3.3 armlink
armlink是鏈接器,它把各個O文件鏈接組合在一起生成ELF格式的AXF文件,AXF文件是可執(zhí)行的,下載器把該文件中的指令代碼下載到芯片后, 該芯片就能運行程序了;利用armlink還可以控制程序存儲到指定的ROM或RAM地址。 在MDK中可在“Option for Target->Linker”頁面配置armlink選項, 見下圖,armlink與MDK的配置選項:
鏈接器默認是根據(jù)芯片類型的存儲器分布來生成程序的,該存儲器分布被記錄在工程里的sct后綴的文件中,有特殊需要的話可自行編輯該文件, 改變鏈接器的鏈接方式,具體后面我們會詳細講解。
2.3.4 armar、fromelf及用戶指令
armar工具用于把工程打包成庫文件,fromelf可根據(jù)axf文件生成hex、bin文件,hex和bin文件是大多數(shù)下載器支持的下載文件格式。
在MDK中,針對armar和fromelf工具的選項幾乎沒有,僅集成了生成HEX或Lib的選項, 見下圖,控制fromelf生成hex及控制armar生成lib的配置:
例如如果我們想利用fromelf生成bin文件,可以在MDK的“Option for Target->User”頁中添加調用fromelf的指令, 見下圖,在MDK中添加指令:
在User配置頁面中,提供了三種類型的用戶指令輸入框,在不同組的框輸入指令, 可控制指令的執(zhí)行時間,分別是編譯前(Before Compile c/c++ file)、 構建前(Before Build/Rebuild)及構建后(AfterBuild/Rebuild)執(zhí)行。 這些指令并沒有限制必須是arm的編譯工具鏈,例如如果您自己編寫了python腳本, 也可以在這里輸入用戶指令執(zhí)行該腳本。
圖中的生成bin文件指令調用了fromelf工具,緊跟后面的是工具的選項及輸出文件名、輸入文件名。由于fromelf是根據(jù)axf文件生成bin的, 而axf文件又是構建(build)工程后才生成,所以我們把該指令放到“After Build/Rebuild”一欄。
3.MDK工程的文件類型
除了上述編譯過程生成的文件,MDK工程中還包含了各種各樣的文件,下面我們統(tǒng)一介紹, MDK工程的常見文件類型見下表,MDK常見的文件類型:
后綴 | 說明 |
*.uvguix | MDK5 工程的窗口布局文件,在 MDK4 中 *.UVGUI 后綴的文件功能相同 |
*.uvprojx | MDK5 的工程文件,它使用了 XML 格式記錄了工程結構,雙擊它可以打開整個工程,在 MDK4 中 *.UVPROJ 后綴的文件功能相同 |
*.uvoptx | MDK5 的工程配置選項,包含 debugger、trace configuration、breakpooints 以及當前打開的文件,在 MDK4 中 *.UVOPT 后綴的文件功能相同 |
*.ini | 某些下載器的配置記錄文件 |
*.c | C 語言源文件 |
*.cpp | C++ 語言源文件 |
*.h | C/C++ 的頭文件 |
*.s | 匯編語言的源文件 |
*.inc | 匯編語言的頭文件 (使用 “$include” 來包含) |
*.lib | 庫文件 |
*.dep | 整個工程的依賴文件 |
*.d | 描述了對應.o 的依賴的文件 |
*.crf | 交叉引用文件,包含了瀏覽信息 (定義、引用及標識符) |
*.o | 可重定位的對象文件 (目標文件) |
*.bin | 二進制格式的映像文件,是純粹的 FLASH 映像,不含任何額外信息 |
*.hex | Intel Hex 格式的映像文件,可理解為帶存儲地址描述格式的 bin 文件 |
*.elf | 由 GCC 編譯生成的文件,功能跟 axf 文件一樣,該文件不可重定位 |
*.axf | 由 ARMCC 編譯生成的可執(zhí)行對象文件,可用于調試,該文件不可重定位 |
*.sct | 鏈接器控制文件 (分散加載) |
*.scr | 鏈接器產生的分散加載文件 |
*.lnp | MDK 生成的鏈接輸入文件,用于調用鏈接器時的命令輸入 |
*.htm | 鏈接器生成的靜態(tài)調用圖文件 |
*.build_log.htm | 構建工程的日志記錄文件 |
*.lst | C 及匯編編譯器產生的列表文件 |
*.map | 鏈接器生成的列表文件,包含存儲器映像分布 |
*.ini | 仿真、下載器的腳本文件 |
這些文件主要分為MDK相關文件、源文件以及編譯、鏈接器生成的文件。我們以“多彩流水燈”工程為例講解各種文件的功能。
4 源文件
源文件是工程中我們最熟悉的內容了,它們就是我們編寫的各種源代碼,MDK支持c、cpp、h、s、inc類型的源代碼文件, 其中c、cpp分別是c/c++語言的源代碼,h是它們的頭文件,s是匯編文件,inc是匯編文件的頭文件,可使用“$include”語法包含。 編譯器根據(jù)工程中的源文件最終生成機器碼。
4.1 Output目錄下生成的文件
點擊MDK中的編譯按鈕,它會根據(jù)工程的配置及工程中的源文件輸出各種對象和列表文件, 在工程的“Options for Targe->Output->Select Folder for Objects”和 “Options for Targe->Listing->Select Folder for Listings”選項配置它們的輸出路徑, 見下圖,設置Output輸出路徑 和圖 設置Listing輸出路徑:
4.2 lib庫文件
在某些場合下我們希望提供給第三方一個可用的代碼庫,但不希望對方看到源碼,這個時候我們就可以把工程生成lib文件(Library file)提供給對方, 在MDK中可配置“Options for Target->Create Library”選項把工程編譯成庫文件, 見下圖,生成庫文件或可執(zhí)行文件:
工程中生成可執(zhí)行文件或庫文件只能二選一,默認編譯是生成可執(zhí)行文件的,可執(zhí)行文件即我們下載到芯片上直接運行的機器碼。
得到生成的*.lib文件后,可把它像C文件一樣添加到其它工程中,并在該工程調用lib提供的函數(shù)接口, 除了不能看到*.lib文件的源碼,在應用方面它跟C源文件沒有區(qū)別。
4.3 dep、d依賴文件
*.dep和*.d文件(Dependency file)記錄的是工程或其它文件的依賴,主要記錄了引用的頭文件路徑,其中*.dep是整個工程的依賴, 它以工程名命名,而*.d是單個源文件的依賴,它們以對應的源文件名命名。這些記錄使用文本格式存儲,我們可直接使用記事本打開, 見下兩圖,工程的dep文件內容和bsp文件的內容:
審核編輯 黃宇
-
單片機
+關注
關注
6061文章
44881瀏覽量
646232 -
機器碼
+關注
關注
0文章
13瀏覽量
8413 -
MDK
+關注
關注
4文章
211瀏覽量
32483 -
編譯
+關注
關注
0文章
676瀏覽量
33717
發(fā)布評論請先 登錄
Linux操作系統(tǒng)下常見文件類型分析
詳解Linux的文件類型
「正點原子Linux連載」第三十章U-Boot使用實驗(一)
「正點原子NANO STM32F103開發(fā)板資料連載」第三十章 串口 IAP 實驗
Linux快速入門之文件類型及文件屬性
模擬電路網(wǎng)絡課件 第三十節(jié):反饋的基本概念
詳解嵌入式linux文件類型

學習嵌入式linux系統(tǒng)開發(fā),文件類型一定要分清
Allegro中的文件類型后綴匯總

嵌入式linux系統(tǒng)開發(fā)幾大文件類型
你知道嵌入式linux文件類型?

評論