- ARM Cortex-M3嵌入式開(kāi)發(fā)實(shí)例詳解
- 張燕妮編著
- 187字
- 2019-01-09 16:32:30
第3章 LPC1700程序設(shè)計(jì)基礎(chǔ)
本章內(nèi)容是LPC17XX軟件設(shè)計(jì)的基礎(chǔ)。本章主要介紹了MDK開(kāi)發(fā)環(huán)境、ARM公司的CMSIS,以及NXP公司的固件庫(kù)。在MDK部分,主要介紹了工程建立、編譯、調(diào)試等操作。CMSIS作為ARM的軟件設(shè)計(jì)標(biāo)準(zhǔn),對(duì)ARM的軟件設(shè)計(jì)做了各項(xiàng)規(guī)定。NXP公司對(duì)CMSIS做了一些具體實(shí)現(xiàn),并在此基礎(chǔ)上定義了各種針對(duì)LPC17XX外設(shè)的操作函數(shù)與定義。
3.1 RealView MDK開(kāi)發(fā)環(huán)境
RealView MDK開(kāi)發(fā)工具源自德國(guó)的Keil公司,被全球超過(guò)10萬(wàn)的嵌入式開(kāi)發(fā)工程師驗(yàn)證和使用,是ARM公司目前最新推出的針對(duì)各種嵌入式處理器的軟件開(kāi)發(fā)工具。RealView MDK集成了業(yè)內(nèi)最領(lǐng)先的技術(shù),包括μVision集成開(kāi)發(fā)環(huán)境與RealView編譯器。它具有支持ARM7、ARM9和最新的Cortex-M3核處理器,自動(dòng)配置啟動(dòng)代碼,集成Flash燒寫(xiě)模塊,強(qiáng)大的Simulation設(shè)備模擬、性能分析等功能。與ARM之前的工具包ADS等相比,RealView編譯器的最新版本可將性能改善超過(guò)20%。
3.1.1 RealView MDK開(kāi)發(fā)環(huán)境簡(jiǎn)介
RealView MDK開(kāi)發(fā)環(huán)境提供了啟動(dòng)代碼生成向?qū)АS捎趩?dòng)代碼和系統(tǒng)硬件結(jié)合緊密,必須用匯編語(yǔ)言編寫(xiě),所以MDK開(kāi)發(fā)環(huán)境成為許多工程師難以跨越的門(mén)檻。RealView MDK的μVision工具可以幫助用戶自動(dòng)生成完善的啟動(dòng)代碼,并提供圖形化的窗口,便于用戶輕松修改。無(wú)論是初學(xué)者,還是有經(jīng)驗(yàn)的開(kāi)發(fā)工程師,它都能大大節(jié)省時(shí)間,提高開(kāi)發(fā)效率。
μVision IDE是一款集編輯、編譯和項(xiàng)目管理于一身的基于窗口的軟件開(kāi)發(fā)環(huán)境。μVision集成了C語(yǔ)言編譯器、宏編譯、鏈接/定位,以及HEX文件產(chǎn)生器。μVision具有如下特性:
(1)具備功能齊全的源代碼編輯器;
(2)具備用于配置開(kāi)發(fā)工具的設(shè)備庫(kù);
(3)具備用于創(chuàng)建工程和維護(hù)工程的項(xiàng)目管理器;
(4)所有的工具配置都采用對(duì)話框進(jìn)行;
(5)集成了源碼級(jí)的仿真調(diào)試器,包括高速CPU和外設(shè)模擬器;
(6)具備用于往Flash ROM下載應(yīng)用程序的Flash編程工具;
(7)具備完備的開(kāi)發(fā)工具幫助文檔、設(shè)備數(shù)據(jù)表和用戶使用向?qū)А?/p>
RealView MDK具有良好的界面風(fēng)格。如圖3-1所示是一個(gè)典型的μVision調(diào)試界面。

圖3-1 μVision調(diào)試界面
(1)工程區(qū):用于訪問(wèn)文件組和文件,調(diào)試時(shí)可以查看CPU寄存器。
(2)調(diào)試輸出窗口:顯示編譯結(jié)果,以便快速查找錯(cuò)誤的地方,它同時(shí)還是調(diào)試命令窗口,可以用于顯示查找結(jié)果。
(3)內(nèi)存窗口:顯示指定地址內(nèi)存里的內(nèi)容。
(4)代碼窗口:用于查看和編輯源文件。
(5)外設(shè)對(duì)話框:檢查微控制的片上外設(shè)的狀態(tài)。
RealView MDK提供了性能分析器,可根據(jù)模塊或函數(shù)實(shí)現(xiàn)對(duì)程序運(yùn)行時(shí)間、被調(diào)用次數(shù)的統(tǒng)計(jì),可用于代碼優(yōu)化、性能檢測(cè)。該分析器需要在模擬器狀態(tài)下進(jìn)行,如圖3-2所示。

圖3-2 性能分析器
3.1.2 工程創(chuàng)建、編譯
本節(jié)是結(jié)合LPC176X的兼容CMSIS標(biāo)準(zhǔn)外設(shè)的固件驅(qū)動(dòng)庫(kù)(簡(jiǎn)稱(chēng)固件庫(kù))(“LPC175X and LPC176X CMSIS-Compliant Standard Peripheral Firmware Driver Library”)進(jìn)行講解的,該固件庫(kù)提供了CMSIS兼容的驅(qū)動(dòng)程序,這里直接使用這部分驅(qū)動(dòng)程序。本節(jié)不涉及LPC176X的固件庫(kù)內(nèi)容,該部分內(nèi)容將在后續(xù)章節(jié)中介紹。
該固件庫(kù)中有一個(gè)core目錄。該目錄包含啟動(dòng)文件配置信息及CMSIS文件內(nèi)容。該目錄文件的含義參見(jiàn)3.2節(jié)及3.3節(jié)。在本節(jié)中,需要將該目錄復(fù)制到建立工程的目錄中。
一個(gè)項(xiàng)目需要經(jīng)過(guò)以下幾大步:
(1)選擇處理器與啟動(dòng)文件;
(2)配置必備文件;
(3)配置工程信息;
(4)編譯鏈接;
(5)程序下載;
(6)調(diào)試程序。
下面將詳述每個(gè)步驟。
(1)建立工程。在主菜單中選擇“new →new project”命令,建立名為“helloworld”的工程。建立工程之后,會(huì)彈出選擇CPU型號(hào)的對(duì)話框,選擇LPC1768,如圖3-3所示。

圖3-3 選擇CPU型號(hào)
(2)單擊圖3-3中的“OK”按鈕,在彈出的對(duì)話框中確定是否需要復(fù)制啟動(dòng)文件,如圖3-4所示。

圖3-4 是否復(fù)制啟動(dòng)文件
這里選擇否(當(dāng)然可以根據(jù)需要選擇是)。如果該步驟選擇是,將使用Keil自帶的啟動(dòng)文件。該啟動(dòng)文件需要在main函數(shù)里增加SystemInit函數(shù)調(diào)用。如果使用NXP提供的固件庫(kù),則不需在main函數(shù)里調(diào)用SystemInit()函數(shù)。兩者的文件區(qū)別如下:
Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0,=SystemInit;NXP提供的固件庫(kù)中有此調(diào)用,但Keil提供的啟 ;動(dòng)文件無(wú)此啟動(dòng)文件。 BLX R0 LDR R0,=__main BX R0 ENDP
(3)管理項(xiàng)目文件組織。
在工程區(qū)單擊鼠標(biāo)右鍵,會(huì)出現(xiàn)如圖3-5所示的菜單,選擇“Manage Components…”選項(xiàng)。

圖3-5 項(xiàng)目文件組織
在彈出的如圖3-6所示的對(duì)話框中添加相應(yīng)文件。

圖3-6 添加文件
在圖3-6中,在Groups菜單里添加“Source”、“Startup”、“CMSIS-core”3個(gè)管理文件夾,然后在Files菜單里分別針對(duì)各組添加文件:
① startup管理文件夾里添加\Core\CM3\DeviceSupport\NXP\LPC17xx\startup\arm目錄下的startup_LPC17xx.s文件;
② CMSIS-core管理文件夾里分別添加\Core\CM3\CoreSupport目錄下的core_cm3.c;Core\CM3\DeviceSupport\NXP\LPC17xx目錄下的system_LPC17xx.c。
(4)選擇工具集:默認(rèn)情況使用RealView編譯器,如圖3-7所示。對(duì)于計(jì)劃使用GNU編譯器的,請(qǐng)選擇“Use GNU Compiler”。

圖3-7 工具集設(shè)置
(5)工程配置。
在圖3-5中,如果選擇“Options for Target’helloworldProject’”將會(huì)彈出“Options for Target’helloworldProject’”對(duì)話框。
如圖3-8所示是晶振設(shè)置,該時(shí)鐘信息應(yīng)與硬件環(huán)境下的時(shí)鐘信息相同。

圖3-8 晶振設(shè)置
單擊圖3-8中的“Output”選項(xiàng)卡,會(huì)出現(xiàn)如圖3-9所示的配置界面,在該界面上根據(jù)需要設(shè)置輸出文件的目錄信息。各選項(xiàng)的含義如下所示。

圖3-9 設(shè)置編譯輸出路徑及輸出文件信息
(1)Create Executable:生成axf及HEX文件。
(2)Debug Information:用于Debug版本,生成調(diào)試信息,否則無(wú)法進(jìn)行單步調(diào)試。
(3)Create Batch File:生成用于實(shí)現(xiàn)整個(gè)編譯過(guò)程的批處理文件,使用這個(gè)文件可以脫離IDE對(duì)程序進(jìn)行編譯。
(4)Create HEX File:這個(gè)選項(xiàng)在默認(rèn)情況下未被選中,如果要燒錄就必須選中該項(xiàng)。
(5)Browse Information:產(chǎn)生用于在源文件快速定位的信息。
在圖3-10中,在“Include Paths”處添加鏈接目錄“.\Core\CM3\CoreSupport;.\Core\CM3\DeviceSupport\NXP\LPC17xx”。也可以采用圖3-10中右圖所示的方式,使用彈出的“Folder Setup”對(duì)話框進(jìn)行設(shè)置。

圖3-10 定義宏及編譯鏈接路徑
在圖3-10左圖所示的“Options for Target’helloworldProject’”對(duì)話框中,Preprocessor Symbols是添加整個(gè)工程的宏定義。
單擊圖3-10中的“Debug”選項(xiàng)卡,會(huì)出現(xiàn)如圖3-11所示的界面。該頁(yè)面用于設(shè)置程序調(diào)試方式。可選擇模擬器方式,或者選擇仿真器方式。

圖3-11 選擇調(diào)試方式及設(shè)置仿真器類(lèi)型
模擬器的使用注意事項(xiàng):在模擬器中測(cè)試程序,如果在main函數(shù)里定義了局部變量,則使用調(diào)試窗口觀察發(fā)現(xiàn)該變量的運(yùn)行結(jié)果不正常。可以將該變量改成全局變量。對(duì)于有條件能在實(shí)際環(huán)境運(yùn)行的,還是推薦使用實(shí)際環(huán)境運(yùn)行程序。
Flash編程的設(shè)置如圖3-12和圖3-13所示。圖3-12中的“Use Target Driver for Flash Programming”默認(rèn)選擇Ulink仿真器。“Settings”按鈕用于Flash編程的設(shè)置。下載參數(shù)的設(shè)置如圖3-13所示。下載參數(shù)需選擇“LPC17xx IAP 512kB Flash”。該處需要結(jié)合硬件實(shí)際情況進(jìn)行選擇,否則運(yùn)行結(jié)果不正常。

圖3-12 設(shè)置編程器類(lèi)型

圖3-13 設(shè)置Flash下載參數(shù)
(6)準(zhǔn)備好工程文件后,可以按一下F7鍵進(jìn)行編譯。編譯完畢工程文件后,需要將程序下載到LPC17XX中,可以通過(guò)主菜單中的“Flash→Download”命令進(jìn)行下載,如圖3-14所示。如果在圖3-11中選擇的是模擬器方式,則可以跳過(guò)該步。

圖3-14 程序下載
(7)下載完畢程序后,進(jìn)行仿真調(diào)試。通過(guò)主菜單中的“Debug→Start/Stop Debug Session”命令,開(kāi)啟調(diào)試,然后單擊“Run”子菜單進(jìn)行調(diào)試,如圖3-15所示。

圖3-15 調(diào)試
3.1.3 Flash編程器
ULINK2是ARM公司最新推出的配套R(shí)ealView MDK使用的仿真器,如圖3-16所示。開(kāi)發(fā)工程師通過(guò)結(jié)合使用RealView MDK的調(diào)試器和ULINK2,可以方便地在目標(biāo)硬件上進(jìn)行片上調(diào)試(使用on-chip JTAG,SWD和OCDS)、Flash編程。ULINK2可實(shí)現(xiàn)USB通信接口高速下載用戶代碼;查看存儲(chǔ)區(qū)域/寄存器;運(yùn)行快速單步程序;可設(shè)置多個(gè)程序斷點(diǎn);片內(nèi)Flash編程。

圖3-16 ULINK2
ULINK2的特點(diǎn):
(1)具備標(biāo)準(zhǔn)Windows USB驅(qū)動(dòng),支持ULINK2即插即用;
(2)支持基于ARM Cortex-M3的串行調(diào)試;
(3)支持程序運(yùn)行期間的存儲(chǔ)器讀/寫(xiě)、終端仿真和串行調(diào)試輸出;
(4)支持10-pin接線(也支持20-pin連接線)。
3.1.4 簡(jiǎn)易實(shí)例
經(jīng)過(guò)3.1.2節(jié)與3.1.3節(jié)兩小節(jié)的準(zhǔn)備工作,現(xiàn)在開(kāi)始實(shí)現(xiàn)顯示“hello world”。在C語(yǔ)言中,最簡(jiǎn)單的“hello world”只有兩行:
void main () {printf(“hello world”); }
在ARM環(huán)境中,可以通過(guò)UART輸出字符串(第8章中將介紹UART的使用)。本節(jié)使用MDK的模擬器輸出字符串,使之更符合我們學(xué)習(xí)任何一門(mén)語(yǔ)言所見(jiàn)到的第一個(gè)程序設(shè)計(jì)的習(xí)慣。
由于標(biāo)準(zhǔn)庫(kù)函數(shù)的默認(rèn)輸出設(shè)備是顯示器,所以要想實(shí)現(xiàn)在串口或LCD輸出,必須重定義標(biāo)準(zhǔn)庫(kù)函數(shù)里調(diào)用的與輸出設(shè)備相關(guān)的函數(shù)。這里將printf函數(shù)重定向到串口,見(jiàn)serial.c文件。由于printf()之類(lèi)的函數(shù)使用了半主機(jī)模式,使用標(biāo)準(zhǔn)庫(kù)會(huì)導(dǎo)致程序無(wú)法運(yùn)行,所以這里采用#pragma import(__use_no_semihosting) 關(guān)閉半主機(jī)模式,見(jiàn)retarget.c文件。
Serial.c與retarget.c文件,以及配套serial.h文件均在Keil\ARM\Boards\Keil\MCB1700\Blinky目錄下存在(讀者所安裝的mdk目錄)。請(qǐng)自行將其復(fù)制到3.1.3節(jié)中建立的工程目錄下。
創(chuàng)建helloworld.c文件之后,將其添加到3.1.3節(jié)創(chuàng)建的工程中。Helloworld.c文件的內(nèi)容如下:
#include <stdio.h> #include"LPC17xx.H" /*LPC17xx definitions*/ #include "Serial.h" @@@ void main() { SER_init(1); printf("hello world \n"); }
選擇模擬器方式運(yùn)行編譯,可通過(guò)“view→serial windows→Uart#2”看到輸出的“hello world”,如圖3-17所示。

圖3-17 運(yùn)行結(jié)果
3.2 CMSIS——Cortex-M3微控制器軟件接口標(biāo)準(zhǔn)
條條大路通羅馬。ARM7TDMI的年代給出了100條甚至1萬(wàn)條大路通羅馬(供選擇的很多,而且每個(gè)都有著美好前景。但這就跟找對(duì)象/工作一樣,容易挑花眼)。但對(duì)于一個(gè)需要經(jīng)常往來(lái)于羅馬及羅馬之外的地區(qū)的人而言,每次往來(lái)都是不同路線,可能是一件痛苦的事情,畢竟去羅馬不需要那么多次旅游。對(duì)于需要經(jīng)常更換ARM7TDMI芯片型號(hào)及編譯工具的人而言,每次都走一條不同的大路去往羅馬不是一件享受的事情。Cortex-M3的年代變了,它只有一條路(也可以說(shuō)有三條路,根據(jù)編譯器的不同會(huì)有稍微差別),你往返的次數(shù)越多,越熟練,也會(huì)發(fā)現(xiàn)時(shí)間節(jié)省得越多。Cortex-M3的年代就是ARM公司提供CMSIS這一條大路。第1章中不斷提到過(guò)CMSIS,本節(jié)將詳細(xì)講解CMSIS的構(gòu)架。
3.2.1 CMSIS概述
Cortex微控制器軟件接口標(biāo)準(zhǔn)(Cortex Microcontroller Software Interface Standard,CMSIS)是Cortex-M處理器系列具備的與供應(yīng)商無(wú)關(guān)的硬件抽象層。使用CMSIS,可以為處理器和外設(shè)實(shí)現(xiàn)一致且簡(jiǎn)單的軟件接口,從而簡(jiǎn)化軟件的重用,縮短微控制器新開(kāi)發(fā)人員的學(xué)習(xí)過(guò)程,并縮短新設(shè)備的上市時(shí)間。軟件的創(chuàng)建被嵌入式行業(yè)公認(rèn)為主要成本。通過(guò)在所有Cortex-M芯片供應(yīng)商產(chǎn)品中標(biāo)準(zhǔn)化軟件接口,這一成本會(huì)明顯降低,尤其是在創(chuàng)建新項(xiàng)目或?qū)F(xiàn)有軟件遷移到新設(shè)備時(shí)。CMSIS提供了一致軟件接口,改善了軟件移植性和可重復(fù)性。通用的軟件庫(kù)可以存取不同的廠家芯片的設(shè)備庫(kù)函數(shù),減少了學(xué)習(xí)時(shí)間、開(kāi)發(fā)成本、產(chǎn)品化時(shí)間。開(kāi)發(fā)者使用標(biāo)準(zhǔn)化的軟件接口可以快速完成軟件的編寫(xiě)工作。CMSIS提供了編譯器獨(dú)立層,可用不同編譯器進(jìn)行編譯。CMSIS支持主流編譯器(ARMCC,IAR,GNU)。目前CMSIS已經(jīng)發(fā)展到版本3。
CMSIS可以分為以下3個(gè)基本功能層。
(1)核內(nèi)外設(shè)訪問(wèn)層(Core Peripheral Access Layer):包含了命名定義、地址定義、存取內(nèi)核寄存器和外圍設(shè)備的協(xié)助函數(shù),同時(shí)定義了一個(gè)與設(shè)備無(wú)關(guān)的RTOS內(nèi)核接口函數(shù);一些對(duì)特殊用途寄存器的訪問(wèn)都被定義成內(nèi)聯(lián)函數(shù)或內(nèi)嵌匯編的形式。
(2)中間件訪問(wèn)層(Middleware Access Layer):該層用于存儲(chǔ)外設(shè),由ARM公司開(kāi)發(fā),其他芯片廠家擴(kuò)展。
(3)設(shè)備訪問(wèn)層(Device Peripheral Access):用來(lái)定義一些硬件寄存器的地址及對(duì)外設(shè)的訪問(wèn)函數(shù)。另外,芯片廠商會(huì)對(duì)異常向量進(jìn)行擴(kuò)展。設(shè)備訪問(wèn)層由芯片廠商實(shí)現(xiàn)。
通過(guò)使用CMSIS兼容軟件組件,用戶可以重復(fù)使用模板代碼。
如圖3-18所示是CMSIS的組織結(jié)構(gòu)圖。

圖3-18 CMSIS的組織結(jié)構(gòu)圖
3.2.2 CMSIS編碼規(guī)范
CMSIS制定了基本規(guī)范及推薦規(guī)范,供芯片廠家及普通用戶使用。
1.基本規(guī)范
CMSIS的C代碼遵照MISRA 2004規(guī)則,使用標(biāo)準(zhǔn)ANSI C頭文件<stdint.h>中定義的標(biāo)準(zhǔn)數(shù)據(jù)類(lèi)型。
(1)由#define定義的包含表達(dá)式的常數(shù)必須用括號(hào)括起來(lái)。
(2)變量和參數(shù)必須有完整的數(shù)據(jù)類(lèi)型。
(3)CPAL層的函數(shù)必須是可重入的。
(4)CPAL層的函數(shù)不能有阻塞代碼,也就是說(shuō),等待、查詢等循環(huán)必須在其他的軟件層中。
(5)定義每個(gè)異常/中斷的
① 每個(gè)異常處理函數(shù)的后綴是_Handler,每個(gè)中斷處理器函數(shù)的后綴是_IRQHandler;
② 默認(rèn)的異常中斷處理器函數(shù)(弱定義)包含一個(gè)無(wú)限循環(huán);
③ 用#define將中斷號(hào)定義為后綴為_(kāi)IRQn的名稱(chēng)。
2.推薦規(guī)范
(1)定義核寄存器、外設(shè)寄存器和CPU指令名稱(chēng)時(shí)使用大寫(xiě)。
(2)定義外設(shè)訪問(wèn)函數(shù)、中斷函數(shù)名稱(chēng)時(shí)首字母大寫(xiě)。
(3)對(duì)于與某個(gè)外設(shè)對(duì)應(yīng)的函數(shù),一般用該外設(shè)名稱(chēng)作為其前綴。
(4)按照Doxygen規(guī)范撰寫(xiě)函數(shù)的注釋?zhuān)⑨屖褂肅90風(fēng)格(/*注釋*/)或C++風(fēng)格(//注釋?zhuān):瘮?shù)的注釋?xiě)?yīng)包含以下內(nèi)容:
① 一行函數(shù)簡(jiǎn)介;
② 參數(shù)的詳細(xì)解釋?zhuān)?/p>
③ 返回值的詳細(xì)解釋?zhuān)?/p>
④ 函數(shù)功能的詳細(xì)描述。
3.2.3 CMSIS文件結(jié)構(gòu)
本節(jié)結(jié)合LPC17XX分析一下CMSIS的文件結(jié)構(gòu),并說(shuō)明各個(gè)文件的主要功能。文件結(jié)構(gòu)如圖3-19所示。

圖3-19 CMSIS的文件結(jié)構(gòu)
CMSIS各個(gè)文件的對(duì)應(yīng)關(guān)系及功能說(shuō)明如表3-1所示。
表3-1 CMSIS各個(gè)文件的對(duì)應(yīng)關(guān)系及功能說(shuō)明

3.2.4 核內(nèi)外設(shè)訪問(wèn)層
硬件層的數(shù)據(jù)類(lèi)型定義使用了標(biāo)準(zhǔn)ANSI C頭文件stdint.h定義的數(shù)據(jù)類(lèi)型。CMSIS使用了3種標(biāo)記符指定對(duì)寄存器的訪問(wèn)權(quán)限:_I(volatile const)、_O(volatile)、_IO(volatile)。其中_I表示只讀權(quán)限,_O表示只寫(xiě)權(quán)限,_IO表示讀寫(xiě)權(quán)限。
1.Cortex-M內(nèi)核寄存器的存取
在core_cm0.h / core_cm3.h中定義了指令的內(nèi)在函數(shù),用于操作Cortex-M內(nèi)核寄存器,如表3-2所示。
表3-2 內(nèi)核寄存器的函數(shù)

2.Cortex-M指令的調(diào)用
在Coretex的時(shí)代,開(kāi)發(fā)人員幾乎可以不使用匯編語(yǔ)言進(jìn)行開(kāi)發(fā)了。但匯編語(yǔ)言仍然存在,而且在某些場(chǎng)合需要使用。ARM為此提供了一些C語(yǔ)言的封裝函數(shù),用于解決指令系統(tǒng)的調(diào)用問(wèn)題。在core_m0.h/core_m3.h中對(duì)指令系統(tǒng)進(jìn)行了定義。在core_cm0.c/core_cm3.c中實(shí)現(xiàn)了這些函數(shù)。如表3-3所示是CMSIS指令的操作函數(shù)。
表3-3 CMSIS指令的操作函數(shù)

3.嵌套中斷向量訪問(wèn)函數(shù)
第1章中介紹了中斷。中斷的設(shè)置涉及組的配置,以及組優(yōu)先級(jí)、子優(yōu)先級(jí)的設(shè)置,屬于比較復(fù)雜的配置。CMSIS提供了相應(yīng)的函數(shù),可以簡(jiǎn)化配置過(guò)程。
表3-4中給出了如何設(shè)置中斷優(yōu)先級(jí),以及與中斷使能相關(guān)的操作。
表3-4 嵌套中斷函數(shù)

說(shuō)明:IRQn_Type是一個(gè)枚舉定義的數(shù)據(jù)類(lèi)型。Cortex-M3中的處理器異常的起始值為負(fù)值。外部設(shè)備的中斷起始值從0開(kāi)始。IRQn_Type在device.h文件中。嵌套向量中斷中的__NVIC_PRIO_BITS影響NVIC_EncodePriority和NVIC_DecodePriority的使用。
4.NXP實(shí)現(xiàn)的device.h
device.h由芯片廠家提供,NXP公司提供的device.h文件名是LPC17XX.h。該文件實(shí)現(xiàn)了中斷號(hào)的枚舉定義,用于提供所有異常和中斷的配置;提供了core_cm3.h文件中針對(duì)實(shí)際芯片的配置信息;提供了對(duì)LPC17XX數(shù)據(jù)結(jié)構(gòu)和地址映射的訪問(wèn)。
device.h可存取設(shè)備中斷,并通過(guò)使用枚舉方式定義了所有設(shè)備的中斷號(hào)。LPC17XX.h中的定義方式如下:
typedef enum IRQn { /****** Cortex-M3 異常號(hào) ***************************************************/ NonMaskableInt_IRQn =-14, /*!<2 NMI */ MemoryManagement_IRQn =-12, /*!<4 Cortex-M3 存儲(chǔ)管理中斷 */ BusFault_IRQn =-11, /*!<5 Cortex-M3 總線故障中斷 */ UsageFault_IRQn =-10, /*!<6 Cortex-M3 用法故障中斷 */ SVCall_IRQn =-5, /*!<11 Cortex-M3 SV調(diào)用中斷 */ DebugMonitor_IRQn =-4, /*!<12 Cortex-M3 調(diào)試監(jiān)視中斷 */ PendSV_IRQn =-2, /*!<14 Cortex-M3 Pend SV中斷 */ SysTick_IRQn =-1, /*!<15 Cortex-M3 系統(tǒng)定時(shí)器中斷 */ @@@ /****** LPC17XX指定中斷號(hào) *******************************************************/ WDT_IRQn =0, /*!< 看門(mén)狗定時(shí)器中斷 */ TIMER0_IRQn =1, /*!<定時(shí)器0 中斷 */ TIMER1_IRQn =2, /*!< 定時(shí)器1 中斷 */ TIMER2_IRQn =3, /*!< 定時(shí)器2 中斷 */ TIMER3_IRQn =4, /*!< 定時(shí)器3中斷 */ UART0_IRQn =5, /*!<UART0 中斷 */ UART1_IRQn =6, /*!<UART1 中斷 */ UART2_IRQn =7, /*!<UART2 中斷 */ UART3_IRQn =8, /*!<UART3 中斷 */ PWM1_IRQn =9, /*!<PWM1 中斷 */ I2C0_IRQn =10, /*!<I2C0 中斷 */ I2C1_IRQn =11, /*!<I2C1 中斷 */ I2C2_IRQn =12, /*!<I2C2 中斷 */ SPI_IRQn =13, /*!<SPI中斷 */ SSP0_IRQn =14, /*!<SSP0 中斷 */ SSP1_IRQn =15, SSP1 中斷 */ PLL0_IRQn =16, /*!<PLL0 鎖存 (Main PLL) 中斷 */ RTC_IRQn =17, /*!< 實(shí)時(shí)時(shí)鐘中斷 */ EINT0_IRQn =18, /*!< 外部中斷0 */ EINT1_IRQn =19, /*!< 外部中斷1 */ EINT2_IRQn =20, /*!< 外部中斷2 */ EINT3_IRQn =21, /*!< 外部中斷3 */ ADC_IRQn =22, /*!<A/D轉(zhuǎn)換中斷 */ BOD_IRQn =23, /*!<Brown-Out Detect Interrupt */ USB_IRQn =24, /*!<USB中斷 */ CAN_IRQn =25, /*!<CAN中斷 */ DMA_IRQn =26, /*!<GPDMA中斷 */ I2S_IRQn =27, /*!<I2S中斷 */ ENET_IRQn =28, /*!< 網(wǎng)絡(luò) 中斷 */ RIT_IRQn =29, /*!< 可重復(fù)定時(shí)器中斷 */ MCPWM_IRQn =30, /*!< 電機(jī)控制PWM中斷 */ QEI_IRQn =31, /*!<QEI中斷 */ PLL1_IRQn =32, /*!<PLL1 鎖存中斷 */ USBActivity_IRQn =33, /*!<USB活躍中斷 */ CANActivity_IRQn =34 /*!<CAN活躍中斷 */ } IRQn_Type;
由于Cortex-M3對(duì)所有外設(shè)采用了內(nèi)存映射方式,所以LPC17XX.h提供了芯片外設(shè)的內(nèi)存映射訪問(wèn)方式。固件庫(kù)采用了結(jié)構(gòu)體定義寄存器,然后通過(guò)地址強(qiáng)制類(lèi)型轉(zhuǎn)換成結(jié)構(gòu)體。例如,LPC17XX系列處理器的I2C寄存器組的數(shù)據(jù)結(jié)構(gòu)定義如下:
/*-------------Inter-IntegratedCircuit(I2C)---------------*/ typedefstruct { __IOuint32_tI2CONSET; __Iuint32_tI2STAT; __IOuint32_tI2DAT; __IOuint32_tI2ADR0; __IOuint32_tI2SCLH; __IOuint32_tI2SCLL; __Ouint32_tI2CONCLR; __IOuint32_tMMCTRL; __IOuint32_tI2ADR1; __IOuint32_tI2ADR2; __IOuint32_tI2ADR3; __Iuint32_tI2DATA_BUFFER; __IOuint32_tI2MASK0; __IOuint32_tI2MASK1; __IOuint32_tI2MASK2; __IOuint32_tI2MASK3; }LPC_I2C_TypeDef;
LPC17XX處理器I2C接口的基地址定義如下:
#defineLPC_I2C0_BASE(LPC_APB0_BASE+0x1C000)
訪問(wèn)LPC17XX處理器I2C接口的方法如下:
#defineLPC_I2C0((LPC_I2C_TypeDef*)LPC_I2C0_BASE)
5.NXP提供的啟動(dòng)文件startup_LPC17xx.s
在Cortex-M3中斷的使用方面,也是從ARM7轉(zhuǎn)到Cortex-M編程的程序員感到困惑的地方,即在Cortex-M3中,雖然原來(lái)的interrupt修飾符消失了,但需要使用與startup_LPC17XX.s中定義一模一樣的函數(shù)名字去定義中斷。
在startup_LPC17xx.s文件中包含了所有外設(shè)的中斷向量。每個(gè)中斷句柄都定義成了weak屬性,即成為啞函數(shù),這樣中斷句柄可以直接使用應(yīng)用程序里的函數(shù),而不用修改startup_device(即startup_LPC17xx.s)的內(nèi)容。
使用weak屬性后,將通知鏈接器,如果可以使用其他源中的不同符號(hào)實(shí)例,則不同實(shí)例將優(yōu)先于此實(shí)例。weak屬性可與任何符號(hào)的可見(jiàn)性屬性一起使用。
對(duì)于Cortex-M3系列,下列代碼的編寫(xiě)都是相同的,定義中斷向量地址的同時(shí)定義了中斷服務(wù)程序的名字,并都定義在中斷向量表的起始位置。
__Vectors DCD __initial_sp ; 堆棧起始地址 DCD Reset_Handler ; 復(fù)位中斷 DCD NMI_Handler ;NMI句柄 DCD HardFault_Handler ; 硬故障 DCD MemManage_Handler ;MPU故障 DCD BusFault_Handler ; 總線故障 DCD UsageFault_Handler ; 用法故障 DCD 0 ; 保留 DCD 0 ; 保留 DCD 0 ; 保留 DCD 0 ; 保留 DCD SVC_Handler ;SVCall DCD DebugMon_Handler ; 調(diào)試監(jiān)視 DCD 0 ;Reserved DCD PendSV_Handler ;PendSV DCD SysTick_Handler ;SysTick ; 外部中斷,廠商指定中斷 DCD WDT_IRQHandler ;16: 定時(shí)器中斷 DCD TIMER0_IRQHandler ;17: 定時(shí)器0 ? Default_Handler PROC EXPORT WDT_IRQHandler [WEAK];;WEAK聲明其他的同名 標(biāo)號(hào)優(yōu)先于該標(biāo)號(hào)被引用,也就是說(shuō),如果外面聲明了,則會(huì)調(diào)用外面的 EXPORT TIMER0_IRQHandler [WEAK] EXPORT TIMER1_IRQHandler [WEAK] ? WDT_IRQHandler TIMER0_IRQHandler TIMER1_IRQHandler ? B. ENDP
用戶程序可以簡(jiǎn)單定義一個(gè)中斷服務(wù)程序的函數(shù)名字,即替代了原有ARM7TDMI必須采用__irq表示中斷函數(shù)的步驟。簡(jiǎn)單定義函數(shù)的實(shí)例如下所示:
void WDT_IRQHandler (void) { ? }
6.NXP實(shí)現(xiàn)的其他文件
ARM公司提供了system_device.c文件模板,NXP公司將其調(diào)整成system_LPC17xx.c。該文件實(shí)現(xiàn)了:
void SystemInit (void);//設(shè)置微控制器系統(tǒng);主要配置時(shí)鐘;更新SystemCoreClock;SystemInit //由啟動(dòng)文件調(diào)用 void SystemCoreClockUpdate (void);//更新SystemCoreClock變量值。只要內(nèi)核時(shí)鐘改變,該函 //數(shù)必須被調(diào)用 uint32_t SystemCoreClock;//包含系統(tǒng)內(nèi)核時(shí)鐘,該變量可以用來(lái)設(shè)置SysTick時(shí)鐘定時(shí)器,然 //后配置其他參數(shù);也可用于調(diào)試器查詢調(diào)試時(shí)間或配置跟蹤時(shí)鐘速度。在應(yīng)用程序不使用該變量的情況 //下,編譯器必須避免刪除該變量。該變量對(duì)調(diào)試器系統(tǒng)是非常重要的
Cortex-M3提供儀器跟蹤宏單元。該單元主要提供了ITM_SendChar的實(shí)現(xiàn)。但在LPC17XX中沒(méi)有提供該功能。NXP公司有屬于自己的debug_frmwrk.c文件,用于通過(guò)UART進(jìn)行調(diào)試。
3.3 LPC1700 CMSIS標(biāo)準(zhǔn)固件庫(kù)
如果將ARM7TDMI年代對(duì)各種外設(shè)驅(qū)動(dòng)的編寫(xiě)理解成徒步,則針對(duì)LPC1700的芯片,LPC1700的固件庫(kù)可以看成在唯一(CMSIS基礎(chǔ))的一條通往羅馬(Cortex-M3)的大路上的坐騎。雖然現(xiàn)在還有不少人喜歡徒步通往羅馬,但不少?gòu)S家出于商業(yè)性、兼容自己老產(chǎn)品的風(fēng)格習(xí)慣,以及學(xué)習(xí)新產(chǎn)品的需要時(shí)間等原因仍然繼續(xù)使用原有的自己配置、管理各種寄存器的方式。通過(guò)本節(jié)的介紹,你會(huì)發(fā)現(xiàn)坐騎年代絕對(duì)比徒步時(shí)代更方便、更快捷、成本還少。
注意:CMSIS指的是ARM公司提供的,即不管你使用哪個(gè)廠家的Cortex-M3芯片,CMSIS與芯片廠商沒(méi)有任何關(guān)系,僅僅與ARM公司有關(guān)。
本書(shū)談到的固件庫(kù)是指NXP公司提供的,而且是針對(duì)LPC175X/6X的固件庫(kù)。固件庫(kù)因芯片的不同而不同。
3.3.1 固件庫(kù)的組織結(jié)構(gòu)
LPC1700 CMSIS標(biāo)準(zhǔn)固件庫(kù)是LPC17XX的標(biāo)準(zhǔn)外圍器件驅(qū)動(dòng)函數(shù)庫(kù),包括宏定義、數(shù)據(jù)類(lèi)型定義、結(jié)構(gòu)體定義和功能函數(shù)。用戶不需要深刻理解LPC1700的外圍器件就可以編寫(xiě)出外圍功能應(yīng)用程序。
固件庫(kù)遵循CMSIS標(biāo)準(zhǔn)。其使用的芯片主要是LPC176X和LPC175X。NXP公司針對(duì)LPC177X與LPC178X提供了另外一套固件庫(kù),但與本書(shū)使用的固件庫(kù)基本一致。
該固件庫(kù)支持的編譯器是:
(1)CodeSourcery G++ Lite toolchain version 4.3.3;
(2)KEIL的RVMDK 4.0以上;
(3)IAR 5.4。
該固件庫(kù)主要分為內(nèi)核(Core)、驅(qū)動(dòng)(Drivers)、例程、MAKE部分,Lib文件構(gòu)建,其中Core與Drivers是開(kāi)發(fā)的基礎(chǔ)。內(nèi)核部分即為CMSIS的內(nèi)容,其中關(guān)于Cortex-M3的內(nèi)容已經(jīng)在3.2節(jié)做過(guò)介紹,NXP公司實(shí)現(xiàn)了需要廠家移植部分的內(nèi)容。這部分內(nèi)容被稱(chēng)為CMSIS的設(shè)備支持部分。
CMSIS的設(shè)備支持部分提供了LPC17XX設(shè)備支持文件,允許用戶調(diào)用設(shè)備外圍。設(shè)備支持部分包含支持ARM(KEIL MDK)/GCC/IAR編譯器的啟動(dòng)文件、頭文件、系統(tǒng)文件。
(1)啟動(dòng)文件根據(jù)編譯器類(lèi)型分別放在如下目錄下。
① ARM編譯器(KEIL MDK):“\Core\CM3\DeviceSupport\NXP\LPC17xx\startup\arm\startup_LPC17xx.s”。
② GCC編譯器:“\Core\CM3\DeviceSupport\NXP\LPC17xx\startup\gcc\startup_LPC17xx.s”。
③ IAR編譯器:“\Core\CM3\DeviceSupport\NXP\LPC17xx\startup\iar\startup_LPC17xx.s”。
(2)頭文件(LPC17xx.h):LPC17XX外設(shè)設(shè)備的存取層定義了所有LPC17XX的外設(shè),如如何訪問(wèn)ADC寄存器。
(3)系統(tǒng)文件包含了system_LPC17xx.h:與system_LPC17xx.c,定義了設(shè)備的特定配置信息,用于配置LPC17XX的時(shí)鐘。
3.3.2 固件庫(kù)的驅(qū)動(dòng)部分
給LPC17XX外圍設(shè)備提供驅(qū)動(dòng)的部分位于“..\Driver”目錄下。它被分成兩部分:
(1)頭文件部分,提供了宏定義、結(jié)構(gòu)體、枚舉類(lèi)型的定義;
(2)源代碼部分,提供了設(shè)備驅(qū)動(dòng)的函數(shù)部分。
如表3-5所示是固件庫(kù)的組織結(jié)構(gòu)。
表3-5 固件庫(kù)的組織結(jié)構(gòu)

LPC1700驅(qū)動(dòng)庫(kù)包含利用UART端口連接的調(diào)試工具,它包含在兩個(gè)文件中:debug_frmwrk.h與debug_frmwrk.c。
固件庫(kù)中的默認(rèn)端口是UART0,采用115200波特率、8位數(shù)據(jù)、無(wú)奇偶校驗(yàn)、一個(gè)停止位。如表3-6所示是固件庫(kù)中的調(diào)試函數(shù)及其功能描述。
表3-6 固件庫(kù)中的調(diào)試函數(shù)及其功能描述

3.3.3 驅(qū)動(dòng)標(biāo)識(shí)定義
LPC17XX固件庫(kù)中的“l(fā)pc17xx_libcfg.h”文件定義了每個(gè)驅(qū)動(dòng)源文件的使用問(wèn)題。該文件通過(guò)宏定義的方式?jīng)Q定具體的某一個(gè)功能模塊是否可被使用。如表3-7所示為lpc17xx_libcfg.h中的宏定義解釋。
表3-7 lpc17xx_libcfg.h中的宏定義解釋

3.4 小結(jié)
本章是進(jìn)行LPC17XX軟件開(kāi)發(fā)的基礎(chǔ)工作。本章介紹了開(kāi)發(fā)環(huán)境,以及如何使用開(kāi)發(fā)環(huán)境建立第一個(gè)軟件程序。本章還對(duì)CMSIS與LPC17XX固件庫(kù)進(jìn)行了詳細(xì)解釋?zhuān)@兩部分是進(jìn)行LPC17XX開(kāi)發(fā)的基礎(chǔ)。后續(xù)章節(jié)的軟件開(kāi)發(fā)將建立在本章介紹的內(nèi)容基礎(chǔ)上。尤其是CMSIS部分,它是理解軟件設(shè)計(jì)的基礎(chǔ)。
- 計(jì)算機(jī)應(yīng)用
- 空間傳感器網(wǎng)絡(luò)復(fù)雜區(qū)域智能監(jiān)測(cè)技術(shù)
- 工業(yè)機(jī)器人入門(mén)實(shí)用教程(KUKA機(jī)器人)
- PostgreSQL Administration Essentials
- 統(tǒng)計(jì)學(xué)習(xí)理論與方法:R語(yǔ)言版
- 工業(yè)機(jī)器人應(yīng)用案例集錦
- Java組件設(shè)計(jì)
- 大型機(jī)系統(tǒng)應(yīng)用基礎(chǔ)
- 這樣用Word!
- Microsoft Office 365:Exchange Online Implementation and Migration(Second Edition)
- Outlook時(shí)間管理秘笈
- Machine Learning with R Quick Start Guide
- 機(jī)器人輔助C程序設(shè)計(jì)
- 軟件設(shè)計(jì)
- 用MATLAB玩轉(zhuǎn)機(jī)器人