- ARM Cortex-M3嵌入式開(kāi)發(fā)實(shí)例詳解
- 張燕妮編著
- 1472字
- 2019-01-09 16:32:20
第1章 Cortex-M3體系結(jié)構(gòu)
ARM公司是全球領(lǐng)先的半導(dǎo)體知識(shí)產(chǎn)權(quán)(IP)提供商,32位嵌入式微處理器的行業(yè)領(lǐng)先提供商,已推出各種各樣基于通用架構(gòu)的處理器,這些處理器具有高性能和行業(yè)領(lǐng)先的特點(diǎn),而且其系統(tǒng)成本也有所降低。ARM公司擁有至少900芯片生產(chǎn)廠家、工具和軟件的合作伙伴,并已推出一系列(20多種)處理器,可以解決每個(gè)應(yīng)用挑戰(zhàn)。迄今為止,ARM公司已生產(chǎn)出超過(guò)250億個(gè)處理器,每天的銷量超過(guò)1600萬(wàn)個(gè),是真正意義上的嵌入式系統(tǒng)的基礎(chǔ)。
本章主要介紹目前ARM公司的Cortex-M3處理器,包括發(fā)展歷史、處理器結(jié)構(gòu)、各個(gè)功能特征。本章將結(jié)合LPC17XX對(duì)其功能特征進(jìn)行介紹。
1.1 Cortex-M3簡(jiǎn)介
ARM公司的Cortex-M3是一種基于ARMV7構(gòu)架的最新ARM嵌入式內(nèi)核,采用哈佛結(jié)構(gòu),具有低成本、低功耗特點(diǎn)。與ARM7TDMI相比,Cortex-M3具有各種優(yōu)勢(shì)。本節(jié)將介紹ARM的歷史、Cortex-M3的特點(diǎn)及與ARM7TDMI之間的性能對(duì)比。
1.1.1 ARM的歷史
ARM這個(gè)詞既代表了一個(gè)公司,也代表了微處理器,還代表了一項(xiàng)技術(shù)。1991年,ARM公司成立于英國(guó)劍橋,主要出售芯片技術(shù)的授權(quán)(目前已經(jīng)授權(quán)給多家公司)。利用這種授權(quán)關(guān)系,ARM公司很快成為許多全球性RISC標(biāo)準(zhǔn)的締造者。
1.ARM體系結(jié)構(gòu)的版本歷史
ARM體系結(jié)構(gòu)是構(gòu)建每個(gè)ARM處理器的基礎(chǔ)。ARM體系結(jié)構(gòu)支持跨越多個(gè)性能點(diǎn)的實(shí)現(xiàn),并已在許多細(xì)分市場(chǎng)中成為主導(dǎo)的體系結(jié)構(gòu)。ARM體系結(jié)構(gòu)支持非常廣泛的性能,因而可以利用最新的微體系結(jié)構(gòu)技術(shù)獲得極小的ARM處理器實(shí)現(xiàn)和極有效的高級(jí)設(shè)計(jì)實(shí)現(xiàn)。ARM體系結(jié)構(gòu)能夠解決實(shí)現(xiàn)規(guī)模小、性能差和功耗低的問(wèn)題。
ARM體系結(jié)構(gòu)通常描述為精簡(jiǎn)指令集計(jì)算機(jī)(RISC)體系結(jié)構(gòu),它包含以下典型的RISC體系結(jié)構(gòu)特征。
(1)大的、統(tǒng)一的寄存器文件。
(2)簡(jiǎn)單的尋址模式。
(3)統(tǒng)一和固定長(zhǎng)度的指令域,3地址指令格式,簡(jiǎn)化了指令的譯碼。采用3地址指令格式、較多寄存器和對(duì)稱的指令格式便于生成優(yōu)化代碼。
(4)單周期操作。ARM指令系統(tǒng)中的指令只需要執(zhí)行簡(jiǎn)單的和基本的操作,因此其執(zhí)行過(guò)程在一個(gè)機(jī)器周期內(nèi)完成。
(5)固定的32位長(zhǎng)度指令。指令長(zhǎng)度固定為32位,使得指令譯碼結(jié)構(gòu)簡(jiǎn)單,效率提高。
(6)采用指令流水線技術(shù)。
ARM處理器對(duì)基本RISC體系結(jié)構(gòu)進(jìn)行功能擴(kuò)展,實(shí)現(xiàn)了高性能、較小代碼大小、較低功耗和較小硅面積的良好平衡。
ARM體系結(jié)構(gòu)自誕生至今,已經(jīng)發(fā)生了很大的演變,至今已定義了8種不同的版本,用版本號(hào)V1~V8表示。
(1)V1版架構(gòu)只在原型機(jī)ARM1中出現(xiàn)過(guò),其基本指令包括基本的數(shù)據(jù)處理指令(無(wú)乘法),字節(jié)、半字和字的Load/Store指令,轉(zhuǎn)移指令,子程序調(diào)用及鏈接指令,軟件中斷指令,其尋址空間為64MB。
(2)V2版架構(gòu)對(duì)V1版架構(gòu)進(jìn)行了擴(kuò)展,如ARM2與ARM3(V2a版)架構(gòu),增加的指令包括乘法和乘加指令、支持協(xié)處理器操作指令、快速中斷模式指令、SWP/SWPB的最基本的存儲(chǔ)器與寄存器交換指令,其尋址空間為64MB。
(3)V3版架構(gòu)對(duì)ARM體系結(jié)構(gòu)做了較大的改動(dòng),把尋址空間增至32位(4GB),增加了當(dāng)前程序狀態(tài)寄存器CPSR和程序狀態(tài)保存寄存器SPSR,以便于進(jìn)行異常處理;增加了中止和未定義2種處理器模式。ARM6就采用了該版架構(gòu)。該版架構(gòu)的指令集的變化包括增加了MRS/MSR指令(以訪問(wèn)新增的CPSR/SPSR寄存器)及從異常處理返回的指令。
(4)V4版架構(gòu)是目前最廣泛應(yīng)用的ARM體系結(jié)構(gòu),它對(duì)V3版架構(gòu)進(jìn)行了進(jìn)一步擴(kuò)充,有的還引進(jìn)了16位的Thumb指令集,使得ARM的使用變得更加靈活。ARM7、ARM9和StrongARM都采用了該版結(jié)構(gòu)。其指令集中增加的功能包括:增加了符號(hào)化和非符號(hào)化半字及符號(hào)化字節(jié)的存/取指令,增加了16位Thumb指令集,完善了軟件中斷SWI指令的功能,處理器系統(tǒng)模式引進(jìn)特權(quán)方式時(shí)使用用戶寄存器操作,把一些未使用的指令空間捕捉為未定義指令。
(5)V5版架構(gòu)在V4版架構(gòu)基礎(chǔ)上增加了一些新的指令。ARM10和XScale都采用該版架構(gòu)。這些新增指令有帶有鏈接和交換的轉(zhuǎn)移BLX指令、計(jì)數(shù)前導(dǎo)零計(jì)數(shù)CLZ指令、BRK中斷指令、信號(hào)處理指令(V5TE版)、協(xié)處理器的更多可選擇的指令。
(6)V6版架構(gòu)是2001年發(fā)布的。其基本特點(diǎn)包括100%與以前的體系兼容;SIMD媒體擴(kuò)展,使媒體處理速度快了1.75倍;改進(jìn)了內(nèi)存管理,使系統(tǒng)性能提高30%;改進(jìn)了混合端(Endian)與不對(duì)齊數(shù)據(jù)支持,使得小端系統(tǒng)支持大端數(shù)據(jù)(如TCP/IP)。例如,許多RTOS是小端的,為實(shí)時(shí)系統(tǒng)縮短了中斷響應(yīng)時(shí)間,將最壞情況下的35周期減小為11個(gè)周期。
(7)V7版架構(gòu)是2005年發(fā)布的。它使用了能夠帶來(lái)更高性能、功耗效率和代碼密度的Thumb-2技術(shù)。它首次采用了強(qiáng)大的信號(hào)處理擴(kuò)展集,對(duì)H.264和MP3等媒體編解碼提供了加速功能。Cortex-M3處理器采用的就是V7版架構(gòu)。
(8)V8版架構(gòu)開(kāi)始支持64位體系結(jié)構(gòu),它包括以下部分。
① 64位通用寄存器、SP(堆棧指針)和PC(程序計(jì)數(shù)器)。
② 64位數(shù)據(jù)處理和擴(kuò)展的虛擬尋址。
③ 兩種主要執(zhí)行狀態(tài)。
a.AArch64-64位執(zhí)行狀態(tài),包括該狀態(tài)的異常模型、內(nèi)存模型、程序員模型和指令集支持。
b.AArch32-32位執(zhí)行狀態(tài),包括該狀態(tài)的異常模型、內(nèi)存模型、程序員模型和指令集支持。
④ 支持三個(gè)主要指令集。
a.A32(或ARM):32位固定長(zhǎng)度指令集,通過(guò)不同體系結(jié)構(gòu)變體增強(qiáng)。部分32位體系結(jié)構(gòu)執(zhí)行環(huán)境現(xiàn)在稱為AArch32。
b.T32(Thumb):以16位固定長(zhǎng)度指令集的形式引入,隨后在引入Thumb-2技術(shù)時(shí)增強(qiáng)為16位和32位混合長(zhǎng)度指令集。
c.A64:提供與ARM和Thumb指令集有類似功能的32位固定長(zhǎng)度指令集。它隨ARMv8-A一起引入,是一種AArch64指令集。
2.處理器內(nèi)核的歷史
ARM公司開(kāi)發(fā)了多種處理器內(nèi)核,目前廣泛使用的有ARM7系列、ARM9系列、ARM9E系列、ARM11系列、SecurCore系列及Cortex系列。不同處理器內(nèi)核使用不同的體系結(jié)構(gòu)版本。
如表1-1所示是ARM內(nèi)核與ARM體系結(jié)構(gòu)版本的對(duì)應(yīng)關(guān)系。
表1-1 ARM內(nèi)核與ARM體系結(jié)構(gòu)版本的對(duì)應(yīng)關(guān)系

下面對(duì)幾種使用廣泛的ARM內(nèi)核做簡(jiǎn)單介紹。
1)ARM7系列
ARM7系列具有三級(jí)流水、空間統(tǒng)一的指令與數(shù)據(jù)Cache、平均功耗為0.6mW/MHz、時(shí)鐘速度為66MHz、每條指令平均執(zhí)行1.9個(gè)時(shí)鐘周期等特性。其中ARM710、ARM720和ARM740為內(nèi)帶Cache的ARM內(nèi)核。ARM7指令集與Thumb指令集擴(kuò)展組合在一起,可以減少內(nèi)存容量和系統(tǒng)成本。同時(shí),它還利用嵌入式ICE調(diào)試技術(shù)來(lái)簡(jiǎn)化系統(tǒng)設(shè)計(jì),并用一個(gè)DSP增強(qiáng)擴(kuò)展來(lái)改進(jìn)性能。ARM7體系結(jié)構(gòu)是小型、快速、低能耗、集成式的RISC內(nèi)核結(jié)構(gòu)。該產(chǎn)品的典型用途是數(shù)字蜂窩電話和硬盤驅(qū)動(dòng)器等。目前主流的ARM7內(nèi)核是ARM7TDMI、ARM7TDMI-S、ARM7EJ-S、ARM720T?,F(xiàn)在市場(chǎng)上用得最多的ARM7系列有思智浦公司的LPC2000系列微控制器、Samsung公司的S3C44BOX與S3C4510處理器、Atmel公司的AT91FR40162系列處理器、Cirrus公司的EP73xx系列等。該系列包括ARM7TDMI、ARM7TDMI-S、帶有高速緩存處理器宏單元的ARM720T和擴(kuò)充了Jazelle的ARM7EJ-S等。這些處理器提供Thumb 16位壓縮指令集和EmbededICE軟件調(diào)試方式,適用于更大規(guī)模的SoC設(shè)計(jì)中。
ARM7系列廣泛應(yīng)用于多媒體和嵌入式設(shè)備中,包括互聯(lián)網(wǎng)設(shè)備、網(wǎng)絡(luò)和調(diào)制解調(diào)器設(shè)備,以及移動(dòng)電話、PDA等無(wú)線設(shè)備。
2)ARM9E系列
ARM9系列采用了ARMV4T(哈佛)體系結(jié)構(gòu)。由于這種體系結(jié)構(gòu)中的程序和數(shù)據(jù)存儲(chǔ)器在兩個(gè)分開(kāi)的物理空間中,所以取指和執(zhí)行能完全重疊。ARM9采用五級(jí)流水處理及分離的Cache結(jié)構(gòu),平均功耗為0.7mW/MHz。其時(shí)鐘速度為120~200MHz,每條指令平均執(zhí)行1.5個(gè)時(shí)鐘周期。與ARM7系列相似,ARM9系列中的ARM920、ARM940和ARM9E處理器均為含有Cache的CPU核,其性能(速率)為132MIPS(120MHz時(shí)鐘,3.3V供電)或220MIPS(200MHz時(shí)鐘)。ARM9系列同時(shí)也配備了Thumb指令擴(kuò)展、調(diào)試,以及Harvard總線。在生產(chǎn)工藝相同的情況下,其性能(速率)是ARM7TDMI處理器的兩倍。它常用于無(wú)線設(shè)備、儀器儀表、聯(lián)網(wǎng)設(shè)備、機(jī)頂盒設(shè)備、高端打印機(jī)及數(shù)碼相機(jī)應(yīng)用中。ARM9E內(nèi)核在ARM9內(nèi)核的基礎(chǔ)上增加了緊密耦合存儲(chǔ)器TCM及DSP部分。目前主流的ARM9內(nèi)核是ARM920T、ARM922T、ARM940。相關(guān)的處理器芯片有Samsung公司的S3C2510、Cirrus公司的EP93xx系列等。主流的ARM9E內(nèi)核是ARM926EJ-S、ARM946E-S、ARM966E-S等。
3)SecurCore系列
SecurCore系列提供了基于高性能的32位RISC技術(shù)的安全解決方案,該系列具有體積小、功耗低、代碼密度大和性能高等特點(diǎn)。另外,最為特別的是,該系列提供了安全解決方案。它采用軟內(nèi)核技術(shù),以提供最大限度的靈活性,以及防止外部對(duì)其進(jìn)行掃描探測(cè);提供面向智能卡的和低成本的存儲(chǔ)保護(hù)單元MPU,可以靈活地集成用戶自己的安全特性和其他的協(xié)處理器。該系列目前包括SC100、SC110、SC200、SC210共4種產(chǎn)品。
4)ARM11系列
ARM11系列可以在使用130nm工藝技術(shù)、芯片面積小至2.2mm2和功率低至0.24mW/MHz的前提下獲得高達(dá)500MHz的速率。ARM11系列處理器以眾多消費(fèi)產(chǎn)品市場(chǎng)為目標(biāo),推出了許多新的技術(shù),包括針對(duì)媒體處理的SIMD,用以提高安全性能的TrustZone技術(shù),智能能源管理(IEM),以及需要非常高的、可升級(jí)的超過(guò)2600 Dhrystone 2.1 MIPS性能的系統(tǒng)多處理技術(shù)。主要的ARM11系列處理器有ARM1136JF-S、ARM1156T2F-S、ARM1176JZF-S、ARM11 MCORE等多種。
5)ARM Cortex系列
ARM Cortex系列基于ARMV7架構(gòu),又分為Cortex-M、Cortex-R和Cortex-A 3類。ARM Cortex系列的3款產(chǎn)品全都集成了Thumb?-2指令集,可滿足各種不同的日益增長(zhǎng)的市場(chǎng)需求。ARM Cortex系列的3款處理器瞄準(zhǔn)的領(lǐng)域如下。
(1)ARM Cortex-A系列:針對(duì)復(fù)雜操作系統(tǒng)及用戶應(yīng)用設(shè)計(jì)的應(yīng)用處理器。
(2)ARM Cortex-R系列:針對(duì)實(shí)時(shí)系統(tǒng)專用嵌入式處理器。
(3)ARM Cortex-M系列:針對(duì)微控制器和低成本應(yīng)用、專門優(yōu)化的深嵌入式處理器。
Cortex-M3是首款基于ARMV7-M架構(gòu)的處理器,專門瞄準(zhǔn)對(duì)功耗和成本敏感的嵌入式應(yīng)用,是為使其實(shí)現(xiàn)高性能而設(shè)計(jì)的,它大大簡(jiǎn)化了可編程的復(fù)雜性,使得ARM體系結(jié)構(gòu)成為各種應(yīng)用方案(即使是最簡(jiǎn)單的方案)的上佳選擇。
注意:NXP公司的LPC17XX系列屬于Cortex-M3的核;LPC11XX系列屬于Cortex-M0的ARM核。
Cortex系列處理器并沒(méi)有開(kāi)拓新的應(yīng)用領(lǐng)域,從某種意義上講,它是對(duì)原有應(yīng)用領(lǐng)域的主流產(chǎn)品的一次大升級(jí),提供了更好的性能。Cortex系列處理器對(duì)應(yīng)于原有的歷史上的各種處理核。ARM公司給出了各種產(chǎn)品的替代關(guān)系表,如表1-2所示。Cortex系列處理器主要是針對(duì)ARM11、ARM9、ARM7 3款經(jīng)典處理器的升級(jí)。
表1-2 Cortex-M0/M3與ARM7/9/11的替代關(guān)系

1.1.2 Cortex-M3的特征
Cortex-M3是一個(gè)32位處理器內(nèi)核。它基于哈佛構(gòu)架,其指令和數(shù)據(jù)各使用一條總線,集成了分支預(yù)測(cè)、單周期乘法、硬件除法等特性。Cortex-M3增加了MPU,用于重要數(shù)據(jù)的保護(hù)及特權(quán)處理。它適用于高確定性的實(shí)時(shí)應(yīng)用,適用于汽車車體系統(tǒng)、控制系統(tǒng)及無(wú)線網(wǎng)絡(luò)和傳感器等多個(gè)應(yīng)用場(chǎng)合。
Cortex-M3的特點(diǎn)有以下幾個(gè)。
(1)功耗低:Cortex-M3使用了最少的ARM內(nèi)核,內(nèi)核的核心部分(0.18um G)的門數(shù)僅為33000個(gè),并支持?jǐn)U展時(shí)鐘門控和集成睡眠模式,使得Cortex-M3的功耗低,滿足目前的白色家電和無(wú)線網(wǎng)絡(luò)市場(chǎng)對(duì)低功耗的要求。
(2)位帶操作:Cortex-M3支持兩塊位帶存儲(chǔ)區(qū)域,其中一塊區(qū)域是SRAM,另一塊區(qū)域是外設(shè)區(qū)。使用位帶操作可簡(jiǎn)化外設(shè)控制流程。另外,通過(guò)使用布爾變量操作位帶別名區(qū)可實(shí)現(xiàn)對(duì)位帶區(qū)的單位操作,從而降低SRAM的使用率。
(3)采用Thumb?-2指令集,能夠執(zhí)行硬件除法、單周期乘法和位字段操作,從而獲取最佳的性能和代碼大小。
(4)低延遲中斷處理機(jī)制:Cortex-M3處理器中集成的NVIC可實(shí)現(xiàn)硬件中斷處理及低延遲,有利于減弱中斷處理對(duì)處理器性能的影響。NVIC和處理器的緊密集成加快了中斷服務(wù)程序的執(zhí)行速度,并減少了進(jìn)入中斷所需的周期數(shù)。
(5)Cortex-M3 NVIC在設(shè)計(jì)時(shí)是可配置的,最多可提供240個(gè)具有單獨(dú)優(yōu)先級(jí)、動(dòng)態(tài)重設(shè)優(yōu)先級(jí)功能和集成系統(tǒng)時(shí)鐘的系統(tǒng)中斷。
(6)支持兩種工作模式(線程模式和處理器模式)及兩個(gè)等級(jí)(有特權(quán)和無(wú)特權(quán))的代碼訪問(wèn),在不犧牲應(yīng)用程序安全性的前提下執(zhí)行復(fù)雜的開(kāi)放式系統(tǒng)。
(7)豐富的連接功能和性能的組合使基于Cortex-M3的設(shè)備可以有效處理多個(gè)I/O通道和協(xié)議標(biāo)準(zhǔn),如USB OTG(On-The-Go)。
(8)開(kāi)發(fā)工具的多樣化:串行線調(diào)試端口或串行線JTAG調(diào)試端口。
(9)ARM提供標(biāo)準(zhǔn)的CMSIS標(biāo)準(zhǔn)支持。
Cortex-M0/M3是針對(duì)ARM7TDMI-S用戶群體設(shè)計(jì)的,ARM公司給出了將ARM7TDMI-S升級(jí)到Cortex-M0/3的益處,以及ARM7TDMI-S與Cortex-M0/3的性能對(duì)比,如表1-3所示。
表1-3 ARM7TDMI-S與Cortex-M0/3的對(duì)比關(guān)系表

如圖1-1所示是Cortex-M3的內(nèi)部功能接口框圖。

圖1-1 Cortex-M3的內(nèi)部功能接口框圖
NVIC是Cortex-M3處理器中一個(gè)完整的部分,它可以進(jìn)行高度配置,為處理器提供出色的中斷處理能力。在NVIC的標(biāo)準(zhǔn)執(zhí)行中,它提供了1個(gè)非屏蔽中斷(NMI)和32個(gè)通用物理中斷,這些中斷帶有8級(jí)的搶占優(yōu)先權(quán)。NVIC可以通過(guò)綜合選擇配置為1~240個(gè)物理中斷中的任何一個(gè),并帶有多達(dá)256個(gè)優(yōu)先級(jí)。
MPU是Cortex-M3處理器中一個(gè)可選的部分,它通過(guò)保護(hù)用戶應(yīng)用程序中操作系統(tǒng)所使用的重要數(shù)據(jù),分離處理任務(wù)(禁止訪問(wèn)各自的數(shù)據(jù)),禁止訪問(wèn)存儲(chǔ)器區(qū)域,將存儲(chǔ)器區(qū)域定義為只讀,以及對(duì)有可能破壞系統(tǒng)的未知的存儲(chǔ)器訪問(wèn)進(jìn)行檢測(cè)等手段來(lái)改善嵌入式系統(tǒng)的可靠性。
對(duì)Cortex-M3處理器系統(tǒng)的調(diào)試訪問(wèn)是通過(guò)調(diào)試訪問(wèn)端口(Debug Access Port)來(lái)實(shí)現(xiàn)的。該端口可以作為串行線調(diào)試端口(SW-DP)[構(gòu)成一個(gè)兩腳(時(shí)鐘和數(shù)據(jù))接口]或串行線JTAG調(diào)試端口(SWJ-DP)(使能JTAG或SW協(xié)議)使用。SWJ-DP在上電復(fù)位時(shí)默認(rèn)為JTAG模式,并且可以通過(guò)外部調(diào)試硬件所提供的控制序列進(jìn)行協(xié)議的切換。
總線矩陣用來(lái)將處理器和調(diào)試接口與外部總線相連??偩€矩陣與下面的外部總線相連。
(1)I-Code總線:該總線用于從代碼空間取指令和向量,是32位AHB-Lite總線。
(2)D-Code總線:該總線用于對(duì)代碼空間進(jìn)行數(shù)據(jù)加載/存儲(chǔ)及調(diào)試訪問(wèn),是32位AHB-Lite總線。
(3)系統(tǒng)總線:該總線用于對(duì)系統(tǒng)空間執(zhí)行取指令和向量,數(shù)據(jù)加載/存儲(chǔ)及調(diào)試訪問(wèn),是32位AHB-Lite總線。
(4)PPB:該總線用于對(duì)PPB空間進(jìn)行數(shù)據(jù)加載/存儲(chǔ)及調(diào)試訪問(wèn),是32位APB(v2.0)總線。
總線矩陣還對(duì)以下方面進(jìn)行控制。
(1)非對(duì)齊訪問(wèn):總線矩陣將非對(duì)齊的處理器訪問(wèn)轉(zhuǎn)換為對(duì)齊訪問(wèn)。
(2)總線矩陣將位帶別名訪問(wèn)轉(zhuǎn)換為對(duì)位帶區(qū)的訪問(wèn):對(duì)位帶加載進(jìn)行位域提??;對(duì)位帶存儲(chǔ)進(jìn)行原子讀—修改—寫;寫緩沖??偩€矩陣包含一個(gè)單入口寫緩沖區(qū),該緩沖區(qū)使得處理器內(nèi)核不受到總線延遲的影響。
1.2 內(nèi)核寄存器
Cortex-M3處理器擁有R0~R15的寄存器組,其中R13用做堆棧指針SP(SP有兩個(gè),但在同一時(shí)刻只能有一個(gè)可以看到),R14為寄存器,R15為程序計(jì)數(shù)寄存器。Cortex-M3有5個(gè)專用寄存器。
如表1-4所示是Cortex-M3的寄存器表,該表中給出了是否需要特權(quán)才能訪問(wèn)的情況。
表1-4 Cortex-M3的寄存器表

1.2.1 通用寄存器
R0~R12都是32位通用寄存器,用于數(shù)據(jù)操作,保存數(shù)據(jù)或地址值。R0~R7被稱為低寄存器,其余的被稱為高寄存器。16位Thumb指令只能訪問(wèn)R0~R7,而32位Thumb-2指令可以訪問(wèn)所有寄存器。
1.2.2 連接寄存器
連接寄存器在匯編代碼中可以寫成R14或LR。它用于存儲(chǔ)函數(shù)調(diào)用(程序寄存器返回值)和異常的返回信息。當(dāng)執(zhí)行分支(branch)和鏈接(BL)指令或帶有交換的分支和鏈接指令(BLX)時(shí),LR用于接收來(lái)自PC的返回地址。復(fù)位時(shí),LR的數(shù)值為0xFFFFFFFF。
startup_LPC17xx.s文件中定義了__user_initial_stackheap函數(shù),該函數(shù)由MDK自動(dòng)調(diào)用,不用用戶調(diào)用。其格式如下:
__user_initial_stackheap … BX LR;返回
1.2.3 程序計(jì)數(shù)器
程序計(jì)數(shù)器(PC)指向當(dāng)前的程序地址。如果修改它的值,就能改變程序的執(zhí)行流。PC[0]總是0,這是因?yàn)橹噶畹娜≈当仨毎窗胱謱?duì)齊。復(fù)位時(shí),處理器用復(fù)位向量的值加載PC,復(fù)位向量地址為0x00000004。
1.2.4 專用寄存器
Cortex-M3包含了一些專用寄存器,主要有3種類型,5(或者說(shuō)7)個(gè)寄存器,這些寄存器只能通過(guò)MSR或MRS指令操作,無(wú)對(duì)應(yīng)內(nèi)存地址。
(1)程序狀態(tài)寄存器:該寄存器又分為3個(gè)子狀態(tài)寄存器,分別是應(yīng)用程序狀態(tài)寄存器(APSR)、中斷號(hào)狀態(tài)寄存器(IPSR)、執(zhí)行狀態(tài)寄存器(EPSR)。
(2)中斷屏蔽寄存器,有PRIMASK、FAULTMASK、BASEPRI。
(3)控制寄存器(CONTROL)。
1.程序狀態(tài)寄存器
程序狀態(tài)寄存器(如表1-5所示)可以作為一個(gè)整體訪問(wèn)或通過(guò)APSR、IPSR、EPSR形式獨(dú)立訪問(wèn)。程序狀態(tài)寄存器作為一個(gè)整體訪問(wèn)時(shí),寄存器的名字是“xPSR”??梢允褂肕RS指令讀取程序狀態(tài)寄存器的內(nèi)容,使用MSR指令改變APSR的內(nèi)容;EPSR和IPSR為只讀寄存器。CMSIS中的core_cm3.c給出了__get_IPSR, __get_xPSR, __get_APSR 3個(gè)函數(shù)實(shí)現(xiàn)讀取APSR、IPSR與xPSR,其中__get_APSR的代碼如下,該函數(shù)通過(guò)MRS指令讀取APSR。
表1-5 程序狀態(tài)寄存器

__ASM uint32_t __get_APSR(void) { mrs r0, apsr bx lr }
當(dāng)需要讀取EPSR及設(shè)置APSR寄存器時(shí),可通過(guò)以下兩條指令實(shí)現(xiàn):
MRS r0,EPSR MSR APSR,r0
2.中斷屏蔽寄存器
中斷屏蔽寄存器用于實(shí)現(xiàn)對(duì)中斷的開(kāi)放與關(guān)閉。中斷屏蔽寄存器主要有PRIMASK、FAULTMASK、BASEPRI。
(1)PRIMASK:只有一位的寄存器。該寄存器被置1后,除了NMI和硬故障(hard fault)之外的所有異常將被關(guān)閉;寫0,不影響。在特權(quán)模式下,可通過(guò)MSR、MRS、CPS指令對(duì)該寄存器進(jìn)行訪問(wèn)。
(2)FAULTMASK:只有一位的寄存器。該寄存器被置1后,除NMI外的所有異常將被關(guān)閉。在特權(quán)模式下,可通過(guò)MSR、MRS、CPS指令對(duì)該寄存器進(jìn)行訪問(wèn)。
(3)BASEPRI:定義了屏蔽異常的最低優(yōu)先級(jí)。當(dāng)BASEPRI設(shè)置為某數(shù)值時(shí),所有不大于數(shù)值的異常將被屏蔽;寫0,不影響。
對(duì)時(shí)序要求嚴(yán)格的應(yīng)用程序,可以通過(guò)PRIMASK與BASEPRI寄存器臨時(shí)屏蔽中斷,以達(dá)到時(shí)序控制目的。FAULTNASK主要用于在操作系統(tǒng)中關(guān)閉任務(wù)崩潰的各種異常。
CMSIS提供了如下函數(shù),用于讀取或設(shè)置中斷屏蔽寄存器:
uint32_t __get_PRIMASK(void) uint32_t __get_BASEPRI(void) uint32_t __get_FAULTMASK(void) void __set_BASEPRI(uint32_t basePri) void __set_FAULTMASK(uint32_t faultMask) void __set_PRIMASK(uint32_t priMask)
3.控制寄存器
控制寄存器(CONTROL)主要用于定義特權(quán)級(jí)別,以及選擇使用哪個(gè)堆棧指針。
如表1-6所示是控制寄存器的位含義。
表1-6 控制寄存器的位含義

在處理模式下,始終使用主堆棧指針MSP。只有在異常進(jìn)入和返回情況下,才會(huì)更新控制寄存器。
CONTROL[0]:僅當(dāng)在特權(quán)級(jí)下操作時(shí)才允許寫該位。一旦進(jìn)入了用戶級(jí),唯一返回特權(quán)級(jí)的途徑就是觸發(fā)一個(gè)(軟)中斷(SVC指令),再由服務(wù)例程改寫該位。
CMSIS中提供了對(duì)該寄存器進(jìn)行訪問(wèn)及操作的函數(shù):
__get_CONTROL();// 讀取當(dāng)前CONTROL寄存器中的內(nèi)容 __set_CONTROL(x);// 設(shè)置CONTROL寄存器中的內(nèi)容
1.3 操作模式和特權(quán)級(jí)別
Cortex-M3有兩種操作模式,分別是線程模式和處理器模式,它們與ARM7TDM的操作模式有很大的區(qū)別。這兩個(gè)模式的訪問(wèn)方式為特權(quán)和非特權(quán)方式,可以在不犧牲應(yīng)用程序安全的前提下實(shí)現(xiàn)對(duì)復(fù)雜的開(kāi)放式系統(tǒng)的執(zhí)行。
線程模式:用于執(zhí)行應(yīng)用軟件。處理器在退出復(fù)位時(shí)進(jìn)入線程模式。該模式是常用的工作模式。它同時(shí)支持享有特權(quán)的代碼和沒(méi)有特權(quán)的代碼。
處理器模式(handler mode):用于處理異常。處理器在完成異常處理后退回線程模式。該模式中的所有代碼都享有特權(quán)。
軟件執(zhí)行的特權(quán)級(jí)別分別為非特權(quán)等級(jí)(或者稱為用戶等級(jí))和特權(quán)等級(jí)。
非特權(quán):對(duì)MSR和MRS指令的有限訪問(wèn)權(quán)限,且不能執(zhí)行CPS指令;不能訪問(wèn)系統(tǒng)定時(shí)器、NVIC、系統(tǒng)控制模塊;可能限制對(duì)存儲(chǔ)器或外設(shè)的訪問(wèn)。
特權(quán):軟件可使用所有指令,并可訪問(wèn)全部資源。
如圖1-2所示是操作模式與特權(quán)等級(jí)之間的切換過(guò)程。

圖1-2 操作模式與特權(quán)等級(jí)之間的切換過(guò)程
特權(quán)級(jí)下的代碼可以通過(guò)置位CONTROL[0]來(lái)進(jìn)入用戶級(jí)。不管是由于什么原因產(chǎn)生了什么異常,處理器都將用特權(quán)級(jí)來(lái)運(yùn)行其服務(wù)例程,異常返回后,處理器將回到產(chǎn)生異常時(shí)所處的級(jí)別。用戶級(jí)下的代碼不能再通過(guò)試圖修改CONTROL[0]來(lái)回到特權(quán)等級(jí)。它必須通過(guò)SVC指令實(shí)現(xiàn)一個(gè)異常處理器模式,由這個(gè)異常處理器模式來(lái)修改CONTROL[0],然后才能在返回線程模式后拿到特權(quán)等級(jí)。
1.4 存儲(chǔ)器映射
ARM7內(nèi)核沒(méi)有定義存儲(chǔ)器映射,各芯片廠商自己定義了存儲(chǔ)器映射。Cortex-M3內(nèi)核規(guī)定了存儲(chǔ)器映射,從而使得各廠商生產(chǎn)的基于Cortex-M3內(nèi)核的微控制器芯片具有相同的存儲(chǔ)器映射。Cortex-M3留給了各廠商存儲(chǔ)器空間,廠商可在此基礎(chǔ)上進(jìn)行擴(kuò)展使用。本節(jié)將介紹Cortex-M3預(yù)定義的存儲(chǔ)器映射,并說(shuō)明LPC17XX在遵照Cortex-M3的預(yù)定義基礎(chǔ)上使用的預(yù)留空間情況。
1.4.1 地址空間
Cortex-M3采用了預(yù)定義的內(nèi)存映射方式。Cortex-M3的中斷控制器及調(diào)試組件可通過(guò)簡(jiǎn)單的內(nèi)存存儲(chǔ)指令進(jìn)行訪問(wèn),從而使得軟件設(shè)計(jì)適合用C語(yǔ)言編程實(shí)現(xiàn)。預(yù)定義的內(nèi)存方式使得Cortex-M3更優(yōu)化與高度集成。
如圖1-3所示是Cortex-M3預(yù)定義的存儲(chǔ)器映射,其空間是4G(0x00000000~0xFFFFFFFF)。

圖1-3 Cortex-M3預(yù)定義的存儲(chǔ)器映射
程序可以在代碼區(qū)(0x00000000~0x1FFFFFFF)、內(nèi)部SRAM區(qū)及外部RAM區(qū)中執(zhí)行。由于指令總線與數(shù)據(jù)總線是分開(kāi)的,所以最理想的是把程序放到代碼區(qū),從而使取指和數(shù)據(jù)訪問(wèn)各自使用自己的總線。
片上SRAM區(qū)的大小是512MB,用于讓芯片制造商連接片上的SRAM,這個(gè)區(qū)通過(guò)系統(tǒng)總線來(lái)訪問(wèn)。有一個(gè)1MB的區(qū)間被稱為“位帶區(qū)”。該位帶區(qū)還有一個(gè)對(duì)應(yīng)的32MB的“位帶別名(alias)區(qū)”。位帶區(qū)對(duì)應(yīng)的是最低的1MB地址范圍,而位帶別名區(qū)里的每個(gè)字對(duì)應(yīng)的是位帶區(qū)的一個(gè)比特。位帶操作只適用于數(shù)據(jù)訪問(wèn),不適用于取指。通過(guò)位帶的功能,可以把多個(gè)布爾型數(shù)據(jù)打包在單一的字中,但是依然可以從位帶別名區(qū)中像訪問(wèn)普通內(nèi)存一樣地使用它們。
片上外設(shè)區(qū)(0x40000000~0x5FFFFFFF)供片上寄存器使用。這個(gè)區(qū)中也有一個(gè)32MB的位帶別名區(qū),以便于快捷地訪問(wèn)外設(shè)寄存器,其用法與內(nèi)部SRAM區(qū)中的位帶相同。例如,可以方便地訪問(wèn)各種控制位和狀態(tài)位。要注意的是,外設(shè)區(qū)內(nèi)不允許執(zhí)行指令。
0x60000000~0x9FFFFFFF區(qū)域與0xA0000000~0xDFFFFFFF區(qū)域分別用于連接外部RAM和外部設(shè)備,它們之中沒(méi)有位帶。兩者的區(qū)別在于外部RAM區(qū)允許執(zhí)行指令,而外部設(shè)備區(qū)則不允許執(zhí)行指令。
0xE0000000~0xE00FFFFF是Cortex-M3獨(dú)立擁有的區(qū)域,該區(qū)域不提供給芯片制造廠家使用。如圖1-4所示是Cortex-M3的私有外設(shè)總線的內(nèi)存映射圖。私有外設(shè)總線有以下兩條。

圖1-4 Cortex-M3的私有外設(shè)總線的內(nèi)存映射圖
(1)AHB私有外設(shè)總線:只用于CM3內(nèi)部的AHB外設(shè),它們是NVIC,F(xiàn)PB,DWT和ITM。
(2)APB私有外設(shè)總線:既用于CM3內(nèi)部的APB設(shè)備,也用于外部設(shè)備(指的是芯片生產(chǎn)廠家的APB外設(shè))。CM3允許芯片生產(chǎn)廠家增添一些片上APB外設(shè)到APB私有總線上,它們通過(guò)APB接口來(lái)訪問(wèn)。
下面來(lái)看一下LPC17XX是如何使用Cortex-M3規(guī)定的內(nèi)存映射的。如表1-7所示是LPC17XX的內(nèi)存映射。LPC17XX在Cortex-M3的預(yù)定義的代碼區(qū)中有64KB的SRAM,該部分用于執(zhí)行代碼與保存數(shù)據(jù)。
表1-7 LPC17XX的內(nèi)存映射

如圖1-5所示是LPC1768的存儲(chǔ)器映射情況。LPC177X/LPC178X與LPC1768除了AHB外設(shè)(即DMA、USB、以太網(wǎng)及新增加的LCD)的存儲(chǔ)空間不一樣外,其余的APB占用空間幾乎一樣。Cortex-M3的內(nèi)核空間均符合Cortex-M3的存儲(chǔ)空間分配要求。

圖1-5 LPC176X的存儲(chǔ)器映射情況
技巧:編譯程序時(shí),輸出map文件可以查看內(nèi)存分配情況,以及程序代碼、數(shù)據(jù)占用空間情況。
1.4.2 位帶操作
1.位帶概念
位帶(bit-band)操作更像C語(yǔ)言中的union與struct相結(jié)合后的位操作。為了更好地理解它,下面先舉一個(gè)例子:
struct_Bitband_Alias_Bits { Uint32 Alias0:1; … Uint32 Alias31:1; }; @@@ union BitBand_Operator { Uint32 BitBand; struct _Bitband_Alias_Bits Bitband_Alias_Bits; }; BitBand_Operator myBitBand;
由上述程序可知,通過(guò)myBitband. Bitband_Alias_Bits. Alias0的訪問(wèn)是通過(guò)對(duì)myBitBand. BitBand的第0位操作實(shí)現(xiàn)的。
Cortex-M3的位帶操作類似于上面的C語(yǔ)言操作方式,但區(qū)別在于BitBand與Bitband_Alias_Bits是兩塊獨(dú)立的內(nèi)存地址,而且位帶操作中的Alias0代表一個(gè)32位的數(shù)據(jù),但只有最低0位是有效數(shù)據(jù)。
Cortex-M3支持了位帶操作后,可以使用普通的加載/存儲(chǔ)指令來(lái)對(duì)單一的比特進(jìn)行讀/寫。在Cortex-M3中,有兩個(gè)區(qū)中實(shí)現(xiàn)了位帶:一個(gè)是SRAM區(qū)的最低1MB范圍(0x20000000-0x200FFFFF),對(duì)應(yīng)的位帶別名區(qū)是0x22000000~0x23FFFFFF;第二個(gè)則是片內(nèi)外設(shè)區(qū)的最低1MB范圍(0x40000000~0x400FFFFF),對(duì)應(yīng)的別名區(qū)是0x42000000~0x43FFFFFF。
映射公式顯示如何將別名區(qū)中的字與bit-band區(qū)中的對(duì)應(yīng)位或目標(biāo)位關(guān)聯(lián)。映射公式舉例:
bit_word_offset=(byte_offset×32)+(bit_number×4) bit_word_addr=bit_band_base+bit_word_offset
這里:
Bit_word_offset為bit-band存儲(chǔ)區(qū)中的目標(biāo)位的位置; Bit_word_addr為別名存儲(chǔ)區(qū)中映射為目標(biāo)位的字的地址; Bit_band_base是別名區(qū)的開(kāi)始地址; Bit_offset為bit-band區(qū)中包含目標(biāo)位的字節(jié)的編號(hào); Bit_number為目標(biāo)位的位置(0~7)。
如圖1-6所示為SRAM位帶區(qū)與對(duì)應(yīng)的別名區(qū)之間的關(guān)系圖。圖1-6中箭頭所指映射的轉(zhuǎn)換關(guān)系如下:

圖1-6 SRAM位帶區(qū)與對(duì)應(yīng)的別名區(qū)之間的關(guān)系圖
地址0x23FFFFE0的別名字映射為0x200FFFFC的位帶字節(jié)的位0: 0x23FFFFE0=0x22000000+(0xFFFFF*32)+0*4 地址 0x23FFFFEC的別名字映射為 0x200FFFFC的位帶字節(jié)的位 7: 0x23FFFFEC=0x22000000+(0xFFFFF*32)+7*4 地址 0x22000000 的別名字映射為 0x20000000 的位帶字節(jié)的位 0: 0x22000000=0x22000000+(0*32)+0*4 地址 0x220001C的別名字映射為 0x20000000 的位帶字節(jié)的位 0: 0x2200001C=0x22000000+(0*32)+7*4
2.位帶操作方法
向別名區(qū)中的一個(gè)字執(zhí)行寫操作會(huì)更新位帶區(qū)中的單個(gè)位。但并不是別名區(qū)的所有位都有效,別名區(qū)的一個(gè)字的第0位是有效的,會(huì)影響對(duì)應(yīng)位帶區(qū)的數(shù)值,即向別名區(qū)中的一個(gè)字寫入值的位[0]決定了寫入位帶區(qū)中目標(biāo)位的值:寫入一個(gè)位[0]設(shè)為1的值,則會(huì)向位帶位寫入一個(gè)1;寫入一個(gè)位[0]設(shè)為0的值,則會(huì)向位帶位寫入一個(gè)0。
注意:別名字的位[31:1]對(duì)位帶位無(wú)影響,寫入0x01與寫入0xFF效果相同,寫入0x00與寫入0x0E效果相同。
讀取別名區(qū)中的一個(gè)字,如讀取數(shù)據(jù)為
(1)0x00000000,表示位帶區(qū)中的目標(biāo)位被設(shè)為0;
(2)0x00000001,表示位帶區(qū)中的目標(biāo)位被設(shè)為1。
位帶區(qū)的訪問(wèn)可通過(guò)字節(jié)、半字、字的方式進(jìn)行訪問(wèn)。
通過(guò)C語(yǔ)言實(shí)現(xiàn)對(duì)Cortex-M3的位帶操作一般使用宏定義方式進(jìn)行,并通過(guò)“1位帶概念”中的位帶與別名區(qū)映射公式進(jìn)行。下列代碼給出的定義中采用了右移代替乘法運(yùn)算。
/*SRAM的位帶區(qū)與別名區(qū)對(duì)應(yīng)地址*/ #define BITBAND_SRAM_REF 0x20000000 #define BITBAND_SRAM_BASE 0x22000000 // 將位帶地址轉(zhuǎn)換到別名區(qū),其中a代表位帶區(qū)地址,b代表要轉(zhuǎn)換的位帶字節(jié)的位數(shù) #define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + ((a-BITBAND_SRAM_REF)<<5) + (b<<2))) /* 外設(shè)位帶地址宏定義 */ #define BITBAND_PERI_REF 0x40000000 #define BITBAND_PERI_BASE 0x42000000 // 將位帶地址轉(zhuǎn)換到別名區(qū),其中a代表位帶區(qū)地址,b代表要轉(zhuǎn)換的位帶字節(jié)的位數(shù) #define BITBAND_PERI(a,b)((BITBAND_PERI_BASE+((a-BITBAND_PERI_REF)<<5)+(b<<2)))
當(dāng)使用位帶功能時(shí),要訪問(wèn)的變量必須用volatile來(lái)定義。因?yàn)镃編譯器并不知道同一個(gè)比特可以有兩個(gè)地址,所以需要通過(guò)volatile使編譯器每次都如實(shí)地把新數(shù)值寫入存儲(chǔ)器中,而不再出于優(yōu)化的考慮,在中途使用寄存器來(lái)操作數(shù)據(jù)的復(fù)本,直到最后才把復(fù)本寫回——這會(huì)導(dǎo)致按不同的方式訪問(wèn)同一個(gè)位得到不一致的結(jié)果。
小知識(shí):對(duì)于volatile聲明的變量,編譯器在訪問(wèn)該變量的代碼時(shí)不再進(jìn)行優(yōu)化,從而可以提供對(duì)特殊地址的穩(wěn)定訪問(wèn)。
下列程序演示了通過(guò)位帶方式操作SPI控制寄存器的過(guò)程。
/* SRAM的位帶區(qū)與別名區(qū)對(duì)應(yīng)地址*/ #define BITBAND_SRAM_REF 0x20000000 #define BITBAND_SRAM_BASE 0x22000000 // 將位帶地址轉(zhuǎn)換到別名區(qū),其中a代表位帶區(qū)地址,b代表要轉(zhuǎn)換的位帶字節(jié)的位數(shù) #define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + ((a-BITBAND_SRAM_REF)<<5) + (b<<2))) /* 外設(shè)位帶地址宏定義 */ #define BITBAND_PERI_REF 0x40000000 #define BITBAND_PERI_BASE 0x42000000 // 將位帶地址轉(zhuǎn)換到別名區(qū),其中a代表位帶區(qū)地址,b代表要轉(zhuǎn)換的位帶字節(jié)的位數(shù) #define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + ((a-BITBAND_PERI_REF)<<5) + (b<<2))) /* 位帶區(qū)操作函數(shù) */ #define BITBAND_SRAM_ClearBit(a,b) (*(volatile uint32_t *) (BITBAND_SRAM(a,b)) = 0) #define BITBAND_SRAM_SetBit(a,b) (*(volatile uint32_t*)(BITBAND_SRAM(a,b))=1) #define BITBAND_SRAM_GetBit(a,b) (*(volatile uint32_t *) (BITBAND_SRAM(a,b))) @@@ #define BITBAND_PERI_ClearBit(a,b) (*(volatile uint32_t *) (BITBAND_PERI(a,b)) = 0) #define BITBAND_PERI_SetBit(a,b) (*(volatile uint32_t*)(BITBAND_PERI(a,b))=1) #define BITBAND_PERI_GetBit(a,b) (*(volatile uint32_t*)(BITBAND_PERI(a,b))) #define VAR_ADDRESS LPC_GPIO2_BASE//0x2007C000 #define VAR_BIT 3//bit 3 @@@ #define PERI_ADDRESS 0x40020000//SPI控制寄存器地址(S0SPCR) #define PERI_BIT 5//bit 5-Master mode select(主模式選擇) uint32_t temp; uint32_t temp1; @@@ int main(void) { @@@ //SRAM temp = (*(volatile uint32_t *)(VAR_ADDRESS)); temp1 = BITBAND_SRAM_GetBit(VAR_ADDRESS,VAR_BIT); if(temp1==(temp&1<<VAR_BIT)) { ;//可在此設(shè)置斷點(diǎn),驗(yàn)證結(jié)果的正確性 } @@@ //設(shè)置第3位為1 BITBAND_SRAM_SetBit(VAR_ADDRESS,VAR_BIT); temp=(*(volatile uint32_t*)(VAR_ADDRESS)); //temp的第3位為1,即temp=0x8 temp1= BITBAND_SRAM_GetBit(VAR_ADDRESS,VAR_BIT); //temp1 =1 //外設(shè)區(qū)代碼演示 LPC_SPI->SPCR=(1<<5); //直接設(shè)置0x40020000 temp1 = (*(volatile uint32_t *)(PERI_ADDRESS));//讀取0x40020000 temp=BITBAND_PERI_GetBit(PERI_ADDRESS,PERI_BIT); //讀取對(duì)應(yīng)別名區(qū),即temp=1 BITBAND_PERI_ClearBit(PERI_ADDRESS,PERI_BIT); temp=BITBAND_PERI_GetBit(PERI_ADDRESS,PERI_BIT); //temp=0 temp1=(*(volatile uint32_t*)(PERI_ADDRESS)); BITBAND_PERI_SetBit(PERI_ADDRESS,PERI_BIT); temp=BITBAND_PERI_GetBit(PERI_ADDRESS,PERI_BIT); //temp=1 temp1=(*(volatile uint32_t*)(PERI_ADDRESS)); //temp1=0x20,即temp結(jié)果右移5位 while(1); return 0; }
3.位帶操作的用途
對(duì)應(yīng)于LPC17XX的外設(shè),所有外設(shè)(除了以太網(wǎng)、USB、DMA、GPIO以外)都位于位帶操作區(qū)域。APB0與APB1對(duì)應(yīng)的外設(shè)內(nèi)存都屬于位帶區(qū)域。
注意:由于GPIO不屬于位帶區(qū),所以如果經(jīng)常需要設(shè)置引腳狀態(tài)時(shí),不能通過(guò)位帶方式進(jìn)行操作。
1.4.3 端模式
Cortex-M3支持32位字、16位半字、8位字節(jié)數(shù)據(jù)類型。Cortex-M3處理器將存儲(chǔ)器看做一個(gè)從0開(kāi)始增長(zhǎng)的線性集合。存儲(chǔ)器可理解成:
(1)地址0~3保存了第一個(gè)要保存的字。
(2)地址4~7保存了第二個(gè)要保存的字。
Cortex-M3支持大端模式和小端模式(但對(duì)應(yīng)于具體芯片時(shí),可能不遵守這個(gè)約定)??梢酝ㄟ^(guò)讀取AIRCR.ENDIANNESS的位判斷當(dāng)前的端模式。端模式的配置通過(guò)Cortex-M3提供的BIGEND引腳進(jìn)行。
注意:LPC17XX僅支持小端模式,不支持大端模式。它沒(méi)有提供配置引腳。如果程序中出現(xiàn)大端模式需求,需要自己手工解決這個(gè)問(wèn)題(即大端模式需求)。
鑒于LPC17XX僅支持小端模式,本節(jié)僅給出小端模式的概念。
小端模式是指處理器將一個(gè)字的最低(有效)位位字節(jié)存儲(chǔ)在序號(hào)最小的字節(jié)中,將最高(有效)位位字節(jié)存儲(chǔ)在序號(hào)最大的字節(jié)中。圖1-7給出了小端模式下,在地址A到地址A+3之間如何保存一個(gè)字?jǐn)?shù)據(jù)及將數(shù)據(jù)存儲(chǔ)在寄存器中的情況。

圖1-7 小端模式舉例
1.5 總線接口
Cortex-M3內(nèi)部有若干條總線接口,使得Cortex-M3能同時(shí)取指和訪問(wèn)內(nèi)存。本節(jié)將介紹各總線,以及LPC17XX的總線對(duì)應(yīng)的外設(shè)情況。
1.5.1 3級(jí)流水線
原有的ARM7TDMI的指令執(zhí)行速度為0.9MIPS/MHz。目前采用ARMv6構(gòu)建的Cortex-M0已經(jīng)可以達(dá)到這個(gè)執(zhí)行速度,而采用哈佛總線結(jié)構(gòu)的Cortex-M3的指令執(zhí)行速度可達(dá)到1.25 DMIPS/MHz。Cortex-M3處理器使用一個(gè)3級(jí)流水線。流水線的3級(jí)分別是取指、譯碼和執(zhí)行,如圖1-8所示。

圖1-8 Cortex-M3的3級(jí)流水線
由于使用了指令流水線,所以讀PC時(shí)返回的值是當(dāng)前指令的地址+4。例如:
0x1000: MOV R0, PC ; 讀到R0=0x1004,而不是0x1000
這個(gè)偏移量總是4,不管是執(zhí)行16位指令還是32位指令,這就保證了在Thumb和Thumb2之間的一致性。
1.5.2 總線矩陣
總線矩陣用來(lái)將處理器和調(diào)試接口與外部總線相連??偩€矩陣與下面的外部總線相連。
(1)I-Code總線:該總線用于從代碼空間取指令和向量,是32位AHB-Lite總線。
(2)D-Code總線:該總線用于對(duì)代碼空間進(jìn)行數(shù)據(jù)加載/存儲(chǔ)及調(diào)試訪問(wèn),是32位AHB-Lite總線。
(3)系統(tǒng)總線:該總線用于對(duì)系統(tǒng)空間執(zhí)行取指令和向量,數(shù)據(jù)加載/存儲(chǔ)及調(diào)試訪問(wèn),是32位AHB-Lite總線。
(4)PPB:該總線用于對(duì)PPB空間進(jìn)行數(shù)據(jù)加載/存儲(chǔ)及調(diào)試訪問(wèn),是32位APB(v2.0)總線。
注意:對(duì)于多層AHB矩陣,只有當(dāng)多個(gè)主機(jī)試圖同時(shí)訪問(wèn)同一矩陣的從機(jī)端口時(shí),才會(huì)做主機(jī)之間的仲裁。在默認(rèn)情況下,Cortex-M3的D-Code總線有最高優(yōu)先級(jí),然后是I-Code總線。所有其他主機(jī)的優(yōu)先級(jí)較低。
如圖1-9所示是Cortex-M3總線接口示例,該圖結(jié)合LPC17XX,說(shuō)明了系統(tǒng)總線與各個(gè)設(shè)備之間的連接關(guān)系。在LPC17XX中,Cortex-M3內(nèi)核總線通過(guò)多層AHB總線矩陣連接各個(gè)外設(shè)設(shè)備。圖1-9中給出的外設(shè)是LPC17XX的部分外設(shè)。

圖1-9 Cortex-M3總線接口示例
1.I-Code總線
I-Code總線是一條基于AHB-Lite總線協(xié)議的32位總線,負(fù)責(zé)在0x00000000~0x1FFFFFFF之間的取指操作。取指以字的長(zhǎng)度執(zhí)行,即使是對(duì)于16位指令也如此。因此,CPU內(nèi)核可以一次取出兩條16位Thumb指令。
2.D-Code總線
D-Code總線也是一條基于AHB-Lite總線協(xié)議的32位總線,負(fù)責(zé)在0x00000000~0x1FFFFFFF之間的數(shù)據(jù)訪問(wèn)操作。盡管Cortex-M3支持非對(duì)齊訪問(wèn),但該總線不允許這樣操作,這是因?yàn)樘幚砥鞯目偩€接口會(huì)把非對(duì)齊的數(shù)據(jù)傳送都轉(zhuǎn)換成對(duì)齊的數(shù)據(jù)傳送。因此,連接到D-Code總線上的任何設(shè)備都只需要支持AHB-Lite的對(duì)齊訪問(wèn),而不需要支持非對(duì)齊訪問(wèn)。
ARM公司推薦D-Code總線的優(yōu)先級(jí)高于I-Code總線的優(yōu)先級(jí)。
3.系統(tǒng)總線
系統(tǒng)總線也是一條基于AHB-Lite總線協(xié)議的32位總線,負(fù)責(zé)在0x20000000~0xDFFFFFFF和0xE0100000~0xFFFFFFFF之間的所有數(shù)據(jù)傳送,取指和數(shù)據(jù)訪問(wèn)都包括在內(nèi)。和D-Code總線一樣,系統(tǒng)總線的所有數(shù)據(jù)傳送都是對(duì)齊的。
4.私有外設(shè)總線
私有外設(shè)總線是一條基于APB總線協(xié)議的32位總線。此總線負(fù)責(zé)0xE0040000~0xE00FFFFF之間的私有外設(shè)訪問(wèn)。但是由于此APB存儲(chǔ)空間的一部分已經(jīng)被TPIU、ETM及ROM表用掉了,所以只留下0xE0042000~E00FF000這個(gè)區(qū)間用于配接附加的(私有)外設(shè)。
1.6 存儲(chǔ)器保護(hù)單元(MPU)
1.6.1 MPU概述
存儲(chǔ)器保護(hù)單元(MPU)是Cortex-M3選配的功能,用于實(shí)現(xiàn)對(duì)存儲(chǔ)器的保護(hù),從而使軟件更加健壯和可靠。MPU將存儲(chǔ)器映射劃分為多個(gè)區(qū),并定義了每個(gè)區(qū)的位置、大小、訪問(wèn)權(quán)限及存儲(chǔ)器屬性。可定義8個(gè)單獨(dú)的存儲(chǔ)區(qū)及1個(gè)背景區(qū)。存儲(chǔ)區(qū)可重疊,此時(shí)存儲(chǔ)器訪問(wèn)受最大的區(qū)的屬性影響(7的優(yōu)先級(jí)最高,0的優(yōu)先級(jí)最低)。每個(gè)區(qū)域的大小可以是32B~4GB。
背景區(qū)具有與默認(rèn)存儲(chǔ)映射相同的存儲(chǔ)器訪問(wèn)屬性,但只能被特權(quán)軟件訪問(wèn)。
如果程序訪問(wèn)被MPU禁止的存儲(chǔ)區(qū),則處理器會(huì)產(chǎn)生一個(gè)存儲(chǔ)器管理異常。因此,在嵌入式操作系統(tǒng)中,內(nèi)核可根據(jù)執(zhí)行的任務(wù)動(dòng)態(tài)更新MPU區(qū)設(shè)置,從而實(shí)現(xiàn)存儲(chǔ)器保護(hù)。
例如,F(xiàn)reeRTOS實(shí)現(xiàn)了具有MPU功能的FreeRTOS-MPU,用于根據(jù)任務(wù)情況實(shí)現(xiàn)對(duì)存儲(chǔ)區(qū)設(shè)置只讀屬性、將其他區(qū)設(shè)置成不可執(zhí)行及利用xTaskCreateRestricted()生成一些訪問(wèn)受限的任務(wù)。
1.6.2 MPU的寄存器
MPU的寄存器如表1-8所示。
表1-8 MPU的寄存器

TYPE寄存器指示是否存在MPU,以及如果存在,它支持多少個(gè)存儲(chǔ)區(qū)。
CTRL寄存器用于使能MPU;使能默認(rèn)存儲(chǔ)器映射的背景區(qū);在硬故障、不可屏蔽中斷(NMI)和FAULTMASK升級(jí)的處理程序中,使能MPU的使用。
RNR寄存器用于選擇哪個(gè)存儲(chǔ)區(qū)被RBAR和RASR寄存器引用。
RBAR寄存器定義了RNR所選擇MPU區(qū)的基址,并可以更新RNR的值。
RASR寄存器定義了區(qū)的大小和RNR所指定的MPU區(qū)的存儲(chǔ)器屬性,并使能該區(qū),以及其子區(qū)的寄存器匯總。
1.6.3 MPU的使用
CMSIS給出了MPU寄存器的C語(yǔ)言訪問(wèn)方式,主要有MPU->TYPE、MPU->RNR、MPU->RBAR、MPU->RASR、MPU->CTRL,與表1-8中名字相同的寄存器一一對(duì)應(yīng)。MPU的設(shè)置流程如圖1-10所示。

圖1-10 MPU的設(shè)置流程
1.7 中斷和異常
Cortex-M3采用ARMV7-M體系結(jié)構(gòu)中的異常(中斷)模型,取消了原來(lái)在ARM7(如LPC23XX,LPC24XX)系列中的FIQ,但采用了中斷優(yōu)先級(jí),引入了嵌套中斷模式,從而實(shí)現(xiàn)了嵌套中斷,即一個(gè)高優(yōu)先級(jí)的中斷能夠覆蓋或搶占低優(yōu)先級(jí)的中斷。Cortex-M3支持11個(gè)系統(tǒng)異常,最多240個(gè)外部中斷。外設(shè)產(chǎn)生的中斷信號(hào),除了SysTick外,全部連接到NVIC的中斷輸入信號(hào)線上。
注意:LPC17XX的外部中斷是35個(gè)。實(shí)際上芯片制造商并不會(huì)全部使用240個(gè)外部中斷。
所有的異常處理都是在處理模式下實(shí)現(xiàn)的。當(dāng)出現(xiàn)中斷時(shí),處理器的狀態(tài)自動(dòng)保存到堆棧中,并在中斷服務(wù)程序(ISR)結(jié)束時(shí)自動(dòng)從堆棧中恢復(fù)。取出向量和保存狀態(tài)是同時(shí)進(jìn)行的,從而提高了進(jìn)入中斷的效率。Cortex-M3還支持末尾連鎖(Tail-chaining),使得處理器無(wú)須保存和恢復(fù)狀態(tài)便可執(zhí)行連續(xù)的中斷。
注意:末尾連鎖(Tail-chaining)指的是當(dāng)處理器響應(yīng)某中斷時(shí),又發(fā)生了其他優(yōu)先級(jí)較低的中斷,則低優(yōu)先級(jí)的中斷先被掛起。在當(dāng)前中斷執(zhí)行返回后,不再執(zhí)行出棧和入棧操作,直接處理掛起的中斷,就好像后一個(gè)中斷與前一個(gè)中斷的尾連接起來(lái)了,前后只執(zhí)行了一次入棧/出棧操作,從而使得兩個(gè)ISR之間的間隔大大縮短。
Cortex-M3的中斷處理方式與原有的ARM處理中斷方式相比,具有不易丟失中斷的特點(diǎn)。如果一個(gè)發(fā)生的異常不能被即刻響應(yīng),就稱它被“掛起”(pending)。不過(guò),少數(shù)fault異常是不允許被掛起的。一個(gè)異常被掛起的原因,可能是系統(tǒng)當(dāng)前正在執(zhí)行一個(gè)更高優(yōu)先級(jí)異常的服務(wù)例程,或者因相關(guān)掩蔽位的設(shè)置導(dǎo)致該異常被禁能。對(duì)于每個(gè)異常源,在被掛起的情況下,都會(huì)有一個(gè)對(duì)應(yīng)的“掛起狀態(tài)寄存器”保存其異常請(qǐng)求。等到該異常能夠響應(yīng)時(shí),執(zhí)行其服務(wù)例程,這與傳統(tǒng)的ARM是完全不同的。在以前,是由產(chǎn)生中斷的設(shè)備保持住請(qǐng)求信號(hào)的;在Cortex-M3中,則由NVIC的掛起狀態(tài)寄存器來(lái)保持住請(qǐng)求信號(hào)的。于是,哪怕設(shè)備在后來(lái)已經(jīng)釋放了請(qǐng)求信號(hào),曾經(jīng)的中斷請(qǐng)求也不會(huì)錯(cuò)失。
1.7.1 異常類型
Cortex-M3自帶的異常是16個(gè),其中異常號(hào)為0與7~10的異常保留,以供將來(lái)使用。異常主要有以下幾種。
1.復(fù)位
復(fù)位的異常號(hào)為0,優(yōu)先級(jí)為-3(最高優(yōu)先級(jí))。
上電或熱復(fù)位時(shí),復(fù)位啟動(dòng)。異常模型將復(fù)位當(dāng)做一種特殊的異常形式。當(dāng)復(fù)位使能時(shí),處理器可能在一條指令的任何位置停止操作。當(dāng)復(fù)位禁能時(shí),由向量表中的復(fù)位表項(xiàng)提供重新開(kāi)始執(zhí)行的地址。在線程模式下,重新執(zhí)行是特權(quán)執(zhí)行。
2.NMI
不可屏蔽中斷(NMI)可由一個(gè)外設(shè)發(fā)出信號(hào)或由軟件觸發(fā)。這是除復(fù)位外的最高優(yōu)先級(jí)的異常。它被永久性使能,具有固定的優(yōu)先級(jí)-2。NMI不能因任何其他異常的激活而被屏蔽或阻止,不能被除復(fù)位外的其他任何異常搶占。
3.硬故障
硬故障是一種異常,其發(fā)生原因是異常在處理期間出錯(cuò),或異常無(wú)法被任何其他異常機(jī)制管理。硬故障具有固定優(yōu)先級(jí)-1,這意味著它的優(yōu)先級(jí)高于任何具有可配置優(yōu)先級(jí)的異常。
4.存儲(chǔ)器管理故障
存儲(chǔ)器管理故障是一種由與存儲(chǔ)器保護(hù)相關(guān)的故障引發(fā)的異常。對(duì)于指令和數(shù)據(jù)存儲(chǔ)事務(wù),MPU或固定的存儲(chǔ)器保護(hù)約束條件決定此故障。此故障用于終止對(duì)從不執(zhí)行(XN)存儲(chǔ)區(qū)的指令的訪問(wèn),即使MPU被禁能也是如此。
5.總線故障
總線故障是一種異常,由一個(gè)指令或數(shù)據(jù)存儲(chǔ)器事務(wù)的存儲(chǔ)器的相關(guān)故障引發(fā)。這可能源于從一個(gè)存儲(chǔ)器系統(tǒng)總線上檢測(cè)出的錯(cuò)誤。
6.使用故障
使用故障是與指令執(zhí)行相關(guān)的故障導(dǎo)致的一種異常。使用故障包括:
(1)未定義的指令;
(2)非法的非對(duì)齊訪問(wèn);
(3)指令執(zhí)行時(shí)的無(wú)效狀態(tài);
(4)異常返回時(shí)的錯(cuò)誤。
當(dāng)內(nèi)核被配置為報(bào)告使用故障時(shí),以下情況可以導(dǎo)致一個(gè)使用故障:
(1)字和半字存儲(chǔ)器訪問(wèn)時(shí)的非對(duì)齊地址;
(2)除以零。
7.SVCall
SVCall是指執(zhí)行系統(tǒng)服務(wù)調(diào)用指令(SVC)引發(fā)的異常。一次超級(jí)用戶調(diào)用是由SVC指令觸發(fā)的異常。在OS環(huán)境中,應(yīng)用程序可使用SVC指令來(lái)訪問(wèn)OS內(nèi)核函數(shù)和設(shè)備驅(qū)動(dòng)程序。
8.PendSV
PendSV是一個(gè)對(duì)系統(tǒng)級(jí)服務(wù)的中斷驅(qū)動(dòng)請(qǐng)求。在OS環(huán)境中,當(dāng)無(wú)其他有效的異常時(shí),使用PendSV進(jìn)行上下文切換。
9.SysTick
SysTick是當(dāng)系統(tǒng)定時(shí)器達(dá)到零時(shí)產(chǎn)生的異常。軟件也可以產(chǎn)生一個(gè)SysTick。在OS環(huán)境中,處理器可將此異常用做系統(tǒng)節(jié)拍。
10.中斷(IRQ)
中斷(IRQ)是由一個(gè)外設(shè)發(fā)出信號(hào),或由一個(gè)軟件請(qǐng)求產(chǎn)生的異常。所有中斷都與指令執(zhí)行異步。在系統(tǒng)中,外設(shè)使用中斷與處理器進(jìn)行通信。
注意:中斷(IRQ)在LPC17XX中是指一些外設(shè)的中斷,如看門狗、UART的中斷。在LPC176X總共有35個(gè)中斷(LPC177X/LPC178X中為41個(gè))。
1.7.2 異常優(yōu)先級(jí)
Cortex-M3中的異常優(yōu)先級(jí)可決定一個(gè)異常是否能被掩蔽,以及在未掩蔽的情況下何時(shí)可以響應(yīng)。優(yōu)先級(jí)的數(shù)值越小,優(yōu)先級(jí)越高。Cortex-M3支持中斷嵌套,使得高優(yōu)先級(jí)異常會(huì)搶占低優(yōu)先級(jí)異常。有3個(gè)系統(tǒng)異常:復(fù)位,NMI及硬fault,它們有固定的優(yōu)先級(jí),并且它們的優(yōu)先級(jí)號(hào)是負(fù)數(shù),高于所有其他異常。所有其他異常的優(yōu)先級(jí)都是可編程的。
異常優(yōu)先級(jí)的設(shè)置分為兩步:
(1)設(shè)置組優(yōu)先級(jí)有效位(LPC17XX通過(guò)設(shè)置系統(tǒng)控制寄存器AIRCR[10:8]實(shí)現(xiàn));
(2)設(shè)置組優(yōu)先級(jí)及子優(yōu)先級(jí)(LPC17XX通過(guò)設(shè)置各自的IPRx或系統(tǒng)控制中的SHPx寄存器實(shí)現(xiàn))。
注意:組優(yōu)先級(jí)在有的書中也叫做搶占優(yōu)先級(jí)或主優(yōu)先級(jí)。有的文獻(xiàn)中使用group priority,有的文獻(xiàn)中使用preempt priority,雖然使用的詞語(yǔ)不一樣,但它們的含義是一樣的,均指具有搶占功能。
如表1-9所示是優(yōu)先級(jí)分組。其中分組位置指的是AIRCR[10:8]中的數(shù)值。IPRx寄存器分成搶占優(yōu)先級(jí)與子優(yōu)先級(jí)兩部分。
表1-9 優(yōu)先級(jí)分組

如果有多個(gè)掛起異常共用相同的組優(yōu)先級(jí),則需使用次優(yōu)先級(jí)區(qū)來(lái)決定同組中異常的優(yōu)先級(jí),這就是同組內(nèi)的次優(yōu)先級(jí)。組優(yōu)先級(jí)和次優(yōu)先級(jí)的結(jié)合就是通常所說(shuō)的優(yōu)先級(jí)。如果兩個(gè)掛起異常具有相同的優(yōu)先級(jí),則掛起異常的編號(hào)越低,優(yōu)先級(jí)越高。這與優(yōu)先級(jí)機(jī)制是一致的。
搶占優(yōu)先級(jí)(組優(yōu)先級(jí))決定了搶占行為:當(dāng)系統(tǒng)正在響應(yīng)某異常L時(shí),如果來(lái)了搶占優(yōu)先級(jí)更高的異常H,則H可以搶占L。只有組優(yōu)先級(jí)才能決定中斷異常的搶占。當(dāng)處理器正在執(zhí)行一個(gè)中斷異常處理程序時(shí),另一個(gè)與正在處理中的中斷具有相同組優(yōu)先級(jí)的中斷不會(huì)搶占處理程序。
子優(yōu)先級(jí)處理組內(nèi)優(yōu)先級(jí)的情況:當(dāng)搶占優(yōu)先級(jí)相同的異常有不止一個(gè)掛起時(shí),就最先響應(yīng)子優(yōu)先級(jí)最高的異常。這種優(yōu)先級(jí)分組做出了如下規(guī)定:子優(yōu)先級(jí)至少是1個(gè)位。因此,搶占優(yōu)先級(jí)最多是7個(gè)位,128級(jí)。
從表1-9中可以看出,Cortex-M3允許從比特7處分組,此時(shí)所有的位都表達(dá)子優(yōu)先級(jí),沒(méi)有任何位表達(dá)搶占優(yōu)先級(jí),因此所有優(yōu)先級(jí)可編程的異常之間就不會(huì)發(fā)生搶占——相當(dāng)于在它們之中禁用了Cortex-M3的中斷嵌套機(jī)制。復(fù)位、NMI和硬fault屬于例外情況,它們無(wú)論何時(shí)出現(xiàn),都立即搶占所有中斷(異常)。
CMSIS提供設(shè)置優(yōu)先級(jí)函數(shù):
void NVIC_SetPriorityGrouping(uint32_t PriorityGroup); //如何進(jìn)行優(yōu)先級(jí)分組 void NVIC_SetPriority(IRQn_Type IRQn,uint32_t priority);//設(shè)置中斷源IRQn的優(yōu)先級(jí)情況(包 //含組優(yōu)先級(jí)與子優(yōu)先級(jí)) NVIC_EncodePriority(uint32_tPriorityGroup,uint32_tPreemptPriority,uint32_t SubPriority);;//將組優(yōu) //先級(jí)與子優(yōu)先級(jí)組合起來(lái),用于給NVIC_SetPriority函數(shù)賦值
LPC17XX中存在EINT0、EINT1、EINT2、EINT3四個(gè)外部中斷,在使用時(shí)分別給予了不同優(yōu)先級(jí)。在這里設(shè)定EINT0>EINT1的優(yōu)先級(jí)??梢愿鶕?jù)需要采用兩種方式:一種是設(shè)定不同組,這樣EINT0可以搶占EINT1的優(yōu)先級(jí),并可能存在優(yōu)先級(jí)嵌套方式;另外一種設(shè)定同一組,但EINT0的子優(yōu)先級(jí)高于EINT1的優(yōu)先級(jí)。
程序代碼如下所示。該程序使用宏定義方式來(lái)區(qū)分兩種方式,并根據(jù)需要設(shè)定了INT_MODE的數(shù)值,以及采用了NVIC_EncodePriority簡(jiǎn)化組優(yōu)先級(jí)和子優(yōu)先級(jí)的組合計(jì)算問(wèn)題。
#define P_Group 4 //組屬性定義 #if(INT_MODE==0) //相同組,不同子優(yōu)先級(jí) NVIC_SetPriorityGrouping(P_Group);//設(shè)定組屬性;子優(yōu)先級(jí)為3 NVIC_SetPriority(EINT0_IRQn,NVIC_EncodePriority(P_Group,0,2)); //組優(yōu)先級(jí):0;子優(yōu)先 //級(jí):2 NVIC_SetPriority(EINT3_IRQn,NVIC_EncodePriority(P_Group,0,1)); //組優(yōu)先級(jí):0;子優(yōu)先 //級(jí):1 #else//不同組,搶占模式 NVIC_SetPriorityGrouping(P_Group); //sets group priorities:8-subpriorities:3 NVIC_SetPriority(EINT0_IRQn,NVIC_EncodePriority(P_Group,0,0)); //組優(yōu)先級(jí):0;子優(yōu)先 //級(jí):0 NVIC_SetPriority(EINT3_IRQn,NVIC_EncodePriority(P_Group,1,0)); //組優(yōu)先級(jí):1;子優(yōu)先 //級(jí):0 #endif
1.7.3 異常響應(yīng)過(guò)程
異常響應(yīng)的基本原則就是只要中斷掛起寄存器為0,而且該中斷沒(méi)有被屏蔽,就可進(jìn)入中斷掛起狀態(tài)。如果在進(jìn)入handler模式之前,掛起寄存器被清除掉,則進(jìn)入中斷服務(wù)程序。
如果掛起寄存器被清0(不管是軟件清除,還是通過(guò)進(jìn)入中斷服務(wù)程序方式清除),就可響應(yīng)新的異常觸發(fā)信號(hào)。如果掛起寄存器已經(jīng)為1,對(duì)于外部新的中斷請(qǐng)求,也僅響應(yīng)一次。
異常響應(yīng)的狀態(tài)主要有以下6種。
(1)當(dāng)中斷輸入腳生效后,該中斷就被掛起。即使后來(lái)中斷源取消了中斷請(qǐng)求,已經(jīng)被標(biāo)記成掛起的中斷也被記錄下來(lái)。當(dāng)在系統(tǒng)中它的優(yōu)先級(jí)最高時(shí),它就會(huì)得到響應(yīng),如圖1-11所示。

圖1-11 中斷響應(yīng)
(2)如果在某個(gè)中斷得到響應(yīng)之前,其掛起狀態(tài)被清除了(例如,當(dāng)PRIMASK或FAULTMASK置位時(shí),軟件清除了掛起狀態(tài)標(biāo)志),則中斷被取消,如圖1-12所示。

圖1-12 掛起狀態(tài)被提前清除掉
(3)當(dāng)某中斷的服務(wù)例程開(kāi)始執(zhí)行時(shí),就稱此中斷進(jìn)入了“活躍”狀態(tài),并且其掛起位會(huì)被硬件自動(dòng)清除。在一個(gè)中斷活躍后,直到其服務(wù)例程執(zhí)行完畢,并且返回后,才能對(duì)該中斷的新請(qǐng)求予以響應(yīng)。當(dāng)然,新請(qǐng)求的響應(yīng)也是由硬件自動(dòng)清零并掛起標(biāo)志位的。中斷服務(wù)例程也可以在執(zhí)行過(guò)程中把自己對(duì)應(yīng)的中斷重新掛起(使用時(shí)要注意避免進(jìn)入“死循環(huán)”),如圖1-13所示。

圖1-13 中斷請(qǐng)求被清除
(4)如果中斷源上一直存在請(qǐng)求信號(hào),該中斷就會(huì)在其上次服務(wù)例程返回后再次被置為掛起狀態(tài),在這一點(diǎn)上,CM3和傳統(tǒng)的ARM7TDMI是相同的。這種情況發(fā)生在電平觸發(fā)源類型的中斷過(guò)程中,如圖1-14所示。

圖1-14 請(qǐng)求一直有效
(5)如果某個(gè)中斷在得到響應(yīng)之前,其請(qǐng)求信號(hào)以若干脈沖形式呈現(xiàn),則被視為只有一次中斷請(qǐng)求,多出的請(qǐng)求脈沖全部丟失,這種情況是由于中斷請(qǐng)求過(guò)快造成的。
假如設(shè)計(jì)程序時(shí),將外部中斷EINT0的優(yōu)先級(jí)設(shè)定得比較低,雖然觸發(fā)多次中斷,但因?yàn)槠渌邇?yōu)先級(jí)的中斷一直占用CPU,所以最后將僅表現(xiàn)為響應(yīng)一次中斷。因此,對(duì)中斷的優(yōu)先級(jí)及中斷響應(yīng)時(shí)長(zhǎng)都需要嚴(yán)格規(guī)劃好,否則會(huì)出現(xiàn)各種意想不到的問(wèn)題,如圖1-15所示。

圖1-15 中斷請(qǐng)求多次觸發(fā)
(6)如果在服務(wù)例程執(zhí)行過(guò)程中,中斷請(qǐng)求釋放了,但是在服務(wù)例程返回前又重新被置為有效,則CM3會(huì)記住此動(dòng)作,重新掛起該中斷。例如,使用SysTick時(shí),如果中斷處理程序比較長(zhǎng)(運(yùn)行時(shí)間需要1ms),但時(shí)鐘間隔設(shè)置比較短(設(shè)置成了500μs),這種情況發(fā)生后,程序?qū)⒁恢闭加锰幚砥鳎蔷哂懈邇?yōu)先級(jí)的中斷產(chǎn)生,如圖1-16所示。

圖1-16 中斷掛起狀態(tài)消失后重新觸發(fā)
從最后兩種形式可以看出,中斷的掛起狀態(tài)影響著中斷的響應(yīng)次數(shù)。因?yàn)橹袛鄴炱馉顟B(tài)只能是0和1,無(wú)其他狀態(tài),所以只要該狀態(tài)寄存器被清除,就可以響應(yīng)下一次中斷了。該寄存器如果已經(jīng)為1,則將無(wú)法響應(yīng)新的狀態(tài)。
1.8 指令系統(tǒng)
Cortex-M3不再支持ARM指令,而是支持ARMV6Thumb指令,同時(shí)引入了Thumb-2指令。Thumb-2指令是一種新型混合指令集,融合了16位和32位指令,用于實(shí)現(xiàn)密度和性能的最佳平衡。在不對(duì)性能進(jìn)行折中的情況下,它節(jié)省了許多高集成度系統(tǒng)級(jí)設(shè)計(jì)的總體存儲(chǔ)成本。
Cortex-M3支持的指令可歸納為6大類:數(shù)據(jù)傳送、數(shù)據(jù)處理、分支指令、系統(tǒng)指令、飽和指令和雜項(xiàng)指令。
數(shù)據(jù)傳送指令可:
(1)在兩個(gè)寄存器之間傳送數(shù)據(jù);
(2)在寄存器與存儲(chǔ)器之間傳送數(shù)據(jù);
(3)在寄存器與特殊功能寄存器之間傳送數(shù)據(jù);
(4)將一個(gè)立即數(shù)加載到寄存器中。
數(shù)據(jù)處理指令主要是一些四則運(yùn)算指令與移位操作指令,包含16位與32位操作指令。
分支指令又分為無(wú)條件跳轉(zhuǎn)及有條件跳轉(zhuǎn),如B、BL、CBZ指令。
系統(tǒng)指令主要是一些直接針對(duì)Cortex-M3寄存器的操作指令,如CPSIE和CPSID。
飽和指令主要是SSAT和USAT,用于對(duì)寄存器進(jìn)行飽和操作。
由于目前Cortex-M3進(jìn)行軟件開(kāi)發(fā)時(shí),更多地關(guān)注于C語(yǔ)言開(kāi)發(fā),所以CMSIS也提供了各種對(duì)應(yīng)指令的C語(yǔ)言版本函數(shù)及操作寄存器的C語(yǔ)言函數(shù)。僅僅在Cortex-M3的啟動(dòng)文件涉及部分匯編代碼。
下面將對(duì)啟動(dòng)文件(Startup.s)中涉及的跳轉(zhuǎn)指令和加載指令進(jìn)行解釋說(shuō)明。
啟動(dòng)文件中使用的跳轉(zhuǎn)指令:
B Label ;跳轉(zhuǎn)到Label處對(duì)應(yīng)的地址 BX reg ;跳轉(zhuǎn)到由寄存器reg給出的地址 BLX reg ;跳轉(zhuǎn)到由寄存器reg給出的地址,并根據(jù)REG的LSB切換處理器狀態(tài),還要 ;把轉(zhuǎn)移前的下條指令地址保存到LR
BL和BLX指令可將下一條指令的地址復(fù)制到鏈接寄存器(LR)R14中。使用BL與BLX時(shí)要小心,因?yàn)樗鼈冞€帶有改變狀態(tài)的功能。寄存器reg的LSB必須是1,以確保處理器不會(huì)試圖進(jìn)入ARM狀態(tài)。如果忘記置位LSB,將會(huì)出現(xiàn)UsageFault異常。
加載指令LDR用于把存儲(chǔ)器中的內(nèi)容加載到寄存器中。Startup.s使用了LDR偽指令。如果匯編器發(fā)現(xiàn)要產(chǎn)生的立即數(shù)是一個(gè)程序地址,它會(huì)自動(dòng)地把LSB置位,例如:
LDR r0, =address1 ;R0=0x40001 … address1 0x4000: MOV R0, R1
在這個(gè)例子中,由于匯編器會(huì)認(rèn)出address1是一個(gè)程序地址,所以自動(dòng)置位LSB,即R0的復(fù)制不是0x4000,而是0x4001。另外,如果匯編器發(fā)現(xiàn)要加載的是數(shù)據(jù)地址,則不會(huì)自動(dòng)置位LSB,例如:
LDR R0, =address1 ; 會(huì)把0x4000 原封不動(dòng)地加載到R0 … address1 0x4000: DCD 0x0 ;0x4000 處記錄的是一個(gè)數(shù)據(jù)
至此,我們可以看一下Startup.s里面的使用情況:
IMPORT SystemInit IMPORT __main LDR R0,=SystemInit;自動(dòng)將R0的LSB置位 BLX R0;切換到Thumb狀態(tài),并加載下一條指令 LDR R0,=__main BX R0
由于C語(yǔ)言不能直接訪問(wèn)Cortex-M3指令,所以CMSIS提供了通過(guò)C語(yǔ)言訪問(wèn)指令及直接訪問(wèn)寄存器的方式,這些方式通過(guò)內(nèi)聯(lián)匯編的方式實(shí)現(xiàn)。
表1-10中給出了CMSIS指令關(guān)系。
表1-10 CMSIS指令關(guān)系

1.9 小結(jié)
本章介紹了Cortex-M3的基本框圖、寄存器、存儲(chǔ)器的使用情況及異常的基礎(chǔ)理論,對(duì)比了Cortex-M3與ARM7TDMI,并結(jié)合LPC17XX,給出了一些Cortex-M3具體應(yīng)用于某款芯片時(shí)的一些特點(diǎn)和用法。
本章中的中斷知識(shí)是以后章節(jié)中經(jīng)常使用的內(nèi)容。Cortex-M3對(duì)中斷的處理機(jī)制與ARM7TDMI有非常大的區(qū)別。本章中結(jié)合CMSIS給出了對(duì)中斷進(jìn)行設(shè)置的方法。
本章對(duì)原有ARM7TDMI經(jīng)常涉及的指令系統(tǒng)只做了簡(jiǎn)單介紹。這主要是因?yàn)槟壳癈ortex-M3的產(chǎn)品設(shè)計(jì)是C語(yǔ)言的天下(當(dāng)然對(duì)于ARM公司而言,可能仍是匯編語(yǔ)言的天下,但對(duì)于普通用戶而言,就是C語(yǔ)言的天下了),在Cortex-M3的軟件設(shè)計(jì)中幾乎可以不用了解匯編。ARM公司為Cortex-M3軟件設(shè)計(jì)提供的便捷方法會(huì)在第3章的CMSIS一節(jié)中介紹到。
第2章將介紹進(jìn)行LPC17XX硬件設(shè)計(jì)的基礎(chǔ)理論內(nèi)容。
- 輕松學(xué)C#
- 基于LabWindows/CVI的虛擬儀器設(shè)計(jì)與應(yīng)用
- R Machine Learning By Example
- 讓每張照片都成為佳作的Photoshop后期技法
- Java Web整合開(kāi)發(fā)全程指南
- JavaScript典型應(yīng)用與最佳實(shí)踐
- 人工智能技術(shù)入門
- Linux Shell編程從初學(xué)到精通
- 穿越計(jì)算機(jī)的迷霧
- Apache Spark Quick Start Guide
- 中老年人學(xué)電腦與上網(wǎng)
- JSP通用范例開(kāi)發(fā)金典
- 網(wǎng)絡(luò)安全原理與應(yīng)用
- JSP網(wǎng)絡(luò)開(kāi)發(fā)入門與實(shí)踐
- 數(shù)據(jù)庫(kù)基礎(chǔ):Access