ARM內核屬於RISC結構,因此其指令集有着一些獨特的特色:指令長度固定,指令格式的種類少,尋址方式簡單。因爲ARM處理器採用固定長度的32位指令,所以處理器內部硬件設計可以被簡化。ARM處理器內部的指令譯碼採用硬佈線邏輯,不使用微程序控制,以減小指令的譯碼時間,大部分指令能夠在一個時鐘週期內完成。程序員
ARM處理器的指令按功能可分爲七大類:加載/存儲指令、數據處理指令、乘法指令、跳轉指令、程序狀態寄存器處理指令、協處理器指令和異常中斷指令。算法
須要特別指出的是,ARM處理器的指令集是加載/存儲型的,也即指令集僅能處理寄存器中的數據,並且處理結果都要放回寄存器中,而對系統存儲器的訪問則須要經過專門的加載/存儲指令來完成。編程
按照操做數的特色分,ARM指令能夠分爲無操做數指令、單操做數指令、雙操做數指令和三操做數指令。每條指令都由操做碼域、條件碼域、條件碼設置域、目標操做數、第一操做數寄存器和第二操做數組成。數組
每條ARM指令都是32位的,其格式以下:安全
31 28 27 25 24 21 20 19 16 15 12 11 0 數據結構
條件碼app |
類別碼異步 |
操做碼函數 |
S工具 |
目的寄存器 |
第一操做數 |
第二操做數 |
用ARM指令助記符表示爲:
<opcode> {<cond>} {S} <Rd>, <Rn>, <shift_op2>
每一個域的含義以下:
1) <opcode>:操做碼域,指令編碼的助記符;
2) {<cond>}:條件碼域,指令容許執行的條件編碼。花括號表示此項可缺省。
ARM指令的一個重要特色是能夠條件執行,每條ARM指令的條件碼域包含4位條件碼,共16種。幾乎全部指令均根據CPSR中條件碼的狀態和指令條件碼域的設置有條件的執行。當指令執行條件知足時,指令被執行,不然被忽略。指令條件碼及其助記符後綴表示參見表3.1。
每種條件碼可用兩個字符表示,這兩個字符能夠做爲後綴添加在指令助記符的後面和指令同時使用。例如,跳轉指令B能夠加上後綴EQ變爲BEQ,表示「相等則跳轉」,即當CPSR中的Z標誌置位時發生跳轉。
表3.1 指令的條件碼
條件碼 |
助記符後綴 |
標 志 |
含 義 |
0000 |
EQ |
Z置位 |
相等 |
0001 |
NE |
Z清零 |
不相等 |
0010 |
CS |
C置位 |
無符號數大於或等於 |
0011 |
CC |
C清零 |
無符號數小於 |
0100 |
MI |
N置位 |
負數 |
0101 |
PL |
N清零 |
正數或零 |
0110 |
VS |
V置位 |
溢出 |
0111 |
VC |
V清零 |
未溢出 |
1000 |
HI |
C置位Z清零 |
無符號數大於 |
1001 |
LS |
C清零Z置位 |
無符號數小於或等於 |
1010 |
GE |
N等於V |
帶符號數大於或等於 |
1011 |
LT |
N不等於V |
帶符號數小於 |
1100 |
GT |
Z清零且(N等於V) |
帶符號數大於 |
1101 |
LE |
Z置位或(N不等於V) |
帶符號數小於或等於 |
1110 |
AL |
忽略 |
無條件執行 |
3) {S}:條件碼設置域。這是一個可選項,當在指令中設置{S}域時,指令執行的結果將會影響程序狀態寄存器CPSR中相應的狀態標誌。
例如:
ADD R0,R1,R2; R1與R2的和存放到R0寄存器中,不影響狀態寄存器
ADDS R0,R1,R2; 執行加法的同時影響狀態寄存器
指令中比較特殊的是CMP指令,它不須要加S後綴就默認地根據計算結構更改程序狀態寄存器。
4) <Rd>:目的操做數。ARM指令中的目的操做數老是一個寄存器。若是<Rd>與第一操做數寄存器<Rn>相同,也必需要指明,不能缺省。
5) <Rn>:第一操做數。ARM指令中的第一操做數也必須是個寄存器。
6) <shift_op2>:第二操做數。在第二操做數中能夠是寄存器、內存存儲單元或者當即數。
因爲第二操做數只有12個bit,用第二操做數表示當即數時,其取值範圍爲0~212-1,要表示超出這個範圍的當即數,一般要依靠僞指令實現。
所謂尋址方式就是處理器根據指令中給出的地址信息來尋找物理地址的方式。目前ARM指令系統支持以下幾種常見的尋址方式。
當即尋址也叫當即數尋址,這是一種特殊的尋址方式,操做數自己就在指令中給出,只要取出指令也就取到了操做數。這個操做數被稱爲當即數,對應的尋址方式也就叫作當即尋址。例如如下指令:
ADD R0,R0,#1 ;R0←R0+1
ADD R0,R0,#0x3f ;R0←R0+0x3f
在以上兩條指令中,第二操做數即爲當即數,要求以「#」爲前綴,對於以十六進制表示的當即數,還要求在「#」後加上「0x」,以二進制表示的當即數,要求在「#」後加上「%」。
噹噹即數大於第二操做數的表示範圍時,一般用如下僞指令實現:
LDR R0,=#0xffff0000
寄存器尋址就是利用寄存器中的數值做爲操做數,這種尋址方式是各種微處理器常常採用的一種方式,也是一種執行效率較高的尋址方式。如下指令:
ADD R0,R1,R2 ;R0←R1+R2
該指令的執行效果是將寄存器R1和R2的內容相加,其結果存放在寄存器R0中。
寄存器間接尋址就是以寄存器中的值做爲操做數的地址,而操做數自己存放在存儲器中。例如如下指令:
ADD R0,R1,[R2] ;R0←R1+[R2]
LDR R0,[R1] ;R0←[R1]
STR R0,[R1] ;[R1]←R0
在第一條指令中,以寄存器R2的值做爲操做數的地址,在存儲器中取得一個操做數後與R1相加,結果存入寄存器R0中。
第二條指令將以R1的值爲地址的存儲器中的數據傳送到R0中。
第三條指令將R0的值傳送到以R1的值爲地址的存儲器中。
基址變址尋址就是將寄存器(該寄存器通常稱做基址寄存器)的內容與指令中給出的地址偏移量相加,從而獲得一個操做數的有效地址。變址尋址方式經常使用於訪問某基地址附近的地址單元。採用變址尋址方式的指令常見有如下幾種形式,以下所示:
LDR R0,[R1,#4] ;R0←[R1+4]
LDR R0,[R1,#4]! ;R0←[R1+4]、R1←R1+4
LDR R0,[R1] ,#4 ;R0←[R1]、R1←R1+4
LDR R0,[R1,R2] ;R0←[R1+R2]
在第一條指令中,將寄存器R1的內容加上4造成操做數的有效地址,從而取得操做數存入寄存器R0中。
在第二條指令中,將寄存器R1的內容加上4造成操做數的有效地址,從而取得操做數存入寄存器R0中,而後,R1的內容自增4個字節。
在第三條指令中,以寄存器R1的內容做爲操做數的有效地址,從而取得操做數存入寄存器R0中,而後,R1的內容自增4個字節。
在第四條指令中,將寄存器R1的內容加上寄存器R2的內容造成操做數的有效地址,從而取得操做數存入寄存器R0中。
多寄存器尋址是ARM處理器特有的一種尋址方式。因爲ARM內核有較多的通用寄存器,採用多寄存器尋址方式,一條指令能夠一次完成多個寄存器值的傳送。這種尋址方式能夠用一條指令完成傳送最多16個通用寄存器的值。例如如下指令:
LDMIA R0,{R1,R2,R3,R4} ;R1←[R0]
;R2←[R0+4]
;R3←[R0+8]
;R4←[R0+12]
該指令的後綴IA表示在每次執行完加載/存儲操做後,R0按字長度增長,所以,指令可將連續存儲單元的值傳送到R1~R4。
多個連續的寄存器能夠用「-」符號鏈接;不連續的寄存器用「,」分隔書寫,如上例可寫成:
LDMIA R0,{R1-R4}
LDMIA R0,{R1-R3,R4}
寄存器移位尋址是ARM指令集特有的尋址方式。ARM處理器內嵌桶型移位器(Barrel Shifter),支持數據的各類移位操做。當第二操做數爲寄存器時,能夠加入移位操做選項對它進行各類移位操做。
移位操做包括以下6種類型:
一、LSL(或ASL)邏輯(算術)左移
尋址格式:
通用寄存器,LSL(或ASL) 操做數
完成對通用寄存器中的內容進行邏輯(或算術)的左移操做,按操做數所指定的數量向左移位,低位用零來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, LSL#2 ;將R1中的內容左移兩位後傳送到R0中。
二、LSR邏輯右移
尋址格式:
通用寄存器,LSR 操做數
完成對通用寄存器中的內容進行右移的操做,按操做數所指定的數量向右移位,左端用零來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, LSR#2 ;將R1中的內容右移兩位後傳送到R0中,左端用零來填充。
三、ASR算術右移
尋址格式:
通用寄存器,ASR 操做數
完成對通用寄存器中的內容進行右移的操做,按操做數所指定的數量向右移位,左端用第31位的值來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, ASR#2 ;將R1中的內容右移兩位後傳送到R0中,左端用第31位的值來填充。
四、ROR循環右移
尋址格式:
通用寄存器,ROR 操做數
完成對通用寄存器中的內容進行循環右移的操做,按操做數所指定的數量向右循環移位,左端用右端移出的位來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。顯然,當進行32位的循環右移操做時,通用寄存器中的值不改變。
如:
MOV R0, R1, ROR#2 ;將R1中的內容循環右移兩位後傳送到R0中。
五、RRX帶擴展的循環右移
尋址格式:
通用寄存器,RRX 操做數
完成對通用寄存器中的內容進行帶擴展的循環右移的操做,按操做數所指定的數量向右循環移位,左端用進位標誌位C來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, RRX#2 ;將R1中的內容進行帶擴展的循環右移兩位後傳送到R0中。
與基址變址尋址方式相相似,相對尋址以程序計數器PC的當前值爲基地址,指令中的地址標號做爲偏移量,將二者相加以後獲得操做數的有效地址。如下程序段完成子程序的調用和返回,跳轉指令BL採用了相對尋址方式:
BL NEXT ;跳轉到子程序NEXT處執行
……
NEXT
……
MOV PC,LR ;從子程序返回
堆棧是一種數據結構,按先進後出(First In Last Out,FILO)的方式工做,使用一個稱做堆棧指針的專用寄存器指示當前的操做位置,堆棧指針老是指向棧頂。
當堆棧指針指向最後壓入堆棧的數據時,稱爲滿堆棧(Full Stack),而當堆棧指針指向下一個將要放入數據的空位置時,稱爲空堆棧(Empty Stack)。
同時,根據堆棧的生成方式,又能夠分爲遞增堆棧(Ascending Stack)和遞減堆棧(Decending Stack)。當堆棧由低地址向高地址生成時,稱爲遞增堆棧,當堆棧由高地址向低地址生成時,稱爲遞減堆棧。這樣就有四種類型的堆棧工做方式,ARM微處理器支持這四種類型的堆棧工做方式,即:
1. 滿遞增堆棧(FA):堆棧指針指向最後壓入的數據,且由低地址向高地址生成。
2. 滿遞減堆棧(FD):堆棧指針指向最後壓入的數據,且由高地址向低地址生成。
3. 空遞增堆棧(EA):堆棧指針指向下一個將要放入數據的空位置,且由低地址向高地址生成。
4. 空遞減堆棧(ED):堆棧指針指向下一個將要放入數據的空位置,且由高地址向低地址生成。
本節對ARM指令集的七大類指令進行詳細的描述。
ARM處理器支持加載/存儲指令用於在寄存器和存儲器之間傳送數據,加載指令用於將存儲器中的數據傳送到寄存器,存儲指令則完成相反的操做。經常使用的加載存儲指令以下:
一、LDR指令
LDR指令的格式爲:
LDR{條件} 目的寄存器,<存儲器地址>
LDR指令用於從存儲器中將一個32位的字數據傳送到目的寄存器中。該指令一般用於從存儲器中讀取32位的字數據到通用寄存器,而後對數據進行處理。當程序計數器PC做爲目的寄存器時,指令從存儲器中讀取的字數據被看成目的地址,從而能夠實現程序流程的跳轉。該指令在程序設計中比較經常使用,且尋址方式靈活多樣,請讀者認真掌握。
如:
LDR R0,[R1] ;將存儲器地址爲R1的字數據讀入寄存器R0。
LDR R0,[R1,R2] ;將存儲器地址爲R1+R2的字數據讀入寄存器R0。
LDR R0,[R1,#8] ;將存儲器地址爲R1+8的字數據讀入寄存器R0。
LDR R0,[R1,R2] ! ;將存儲器地址爲R1+R2的字數據讀入寄存器R0,並將
;新地址R1+R2寫入R1。
LDR R0,[R1,#8] ! ;將存儲器地址爲R1+8的字數據讀入寄存器R0,並將新
;地址R1+8寫入R1。
LDR R0,[R1],R2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地
;址R1+R2寫入R1。
LDR R0,[R1,R2,LSL#2]! ;將存儲器地址爲R1+R2×4的字數據讀入寄存器R0,
;並將新地址R1+R2×4寫入R1。
LDR R0,[R1],R2,LSL#2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地
;址R1+R2×4寫入R1。
二、STR指令
STR指令的格式爲:
STR{條件} 源寄存器,<存儲器地址>
STR指令用於從源寄存器中將一個32位的字數據傳送到存儲器中。該指令在程序設計中比較經常使用,且尋址方式靈活多樣,使用方式可參考指令LDR。
如:
STR R0,[R1],#8 ;將R0中的字數據寫入以R1爲地址的存儲器中,並將新地址R1+8寫入R1。
STR R0,[R1,#8] ;將R0中的字數據寫入以R1+8爲地址的存儲器中。
LDR/STR指令均可以加B、H、SB、SH的後綴,分別表示加載/存儲字節、半字、帶符號的字節、帶符號的半字。如LDRB指令表示從存儲器加載一個字節進寄存器。當使用這些後綴時,要注意所使用的存儲器要支持訪問的數據寬度。
三、LDM(或STM)批量數據加載/存儲指令
LDM(或STM)指令的格式爲:
LDM(或STM){條件}{類型} 基址寄存器{!},寄存器列表{∧}
LDM(或STM)指令用於從由基址寄存器所指示的一片連續存儲器到寄存器列表所指示的多個寄存器之間傳送數據,該指令的常見用途是將多個寄存器的內容入棧或出棧。其中,{類型}爲如下幾種狀況:
IA 每次傳送後地址加1;
IB 每次傳送前地址加1;
DA 每次傳送後地址減1;
DB 每次傳送前地址減1;
FD 滿遞減堆棧;
ED 空遞減堆棧;
FA 滿遞增堆棧;
EA 空遞增堆棧;
{!}爲可選後綴,若選用該後綴,則當數據傳送完畢以後,將最後的地址寫入基址寄存器,不然基址寄存器的內容不改變。
基址寄存器不容許爲R15,寄存器列表能夠爲R0~R15的任意組合。
{∧}爲可選後綴,當指令爲LDM且寄存器列表中包含R15,選用該後綴時表示:除了正常的數據傳送以外,還將SPSR複製到CPSR。同時,該後綴還表示傳入或傳出的是用戶模式下的寄存器,而不是當前模式下的寄存器。
如:
STMFD R13!,{R0,R4-R12,LR} ;將寄存器列表中的寄存器(R0,R4到R12,LR)存入堆棧。
LDMFD R13!,{R0,R4-R12,PC} ;將堆棧內容恢復到寄存器(R0,R4到R12,LR)。
四、SWP數據交換指令
SWP指令的格式爲:
SWP{條件} 目的寄存器,源寄存器1,[源寄存器2]
SWP指令用於將源寄存器2所指向的存儲器中的字數據傳送到目的寄存器中,同時將源寄存器1中的字數據傳送到源寄存器2所指向的存儲器中。顯然,當源寄存器1和目的寄存器爲同一個寄存器時,指令交換該寄存器和存儲器的內容。
如:
SWP R0,R1,[R2] ;將R2所指向的存儲器中的字數據傳送到R0,同時將R1中的字數據傳送到R2所指向的存儲單元。
SWP R0,R0,[R1] ;該指令完成將R1所指向的存儲器中的字數據與R0中的字數據交換。
數據處理指令可分爲數據傳送指令、算術邏輯運算指令和比較指令等。
數據傳送指令用於在寄存器和存儲器之間進行數據的雙向傳輸。
算術邏輯運算指令完成經常使用的算術與邏輯的運算,該類指令不但將運算結果保存在目的寄存器中,同時更新CPSR中的相應條件標誌位。
比較指令不保存運算結果,只更新CPSR中相應的條件標誌位。
一、 MOV指令
MOV指令的格式爲:
MOV{條件}{S} 目的寄存器,源操做數
MOV指令可完成從另外一個寄存器、被移位的寄存器或將一個當即數加載到目的寄存器。其中S選項決定指令的操做是否影響CPSR中條件標誌位的值,當沒有S時指令不更新CPSR中條件標誌位的值。
如:
MOV R1,R0 ;將寄存器R0的值傳送到寄存器R1
MOV PC,R14 ;將寄存器R14的值傳送到PC,經常使用於子程序返回
MOV R1,R0,LSL#3 ;將寄存器R0的值左移3位後傳送到R1
二、 MVN指令
MVN指令的格式爲:
MVN{條件}{S} 目的寄存器,源操做數
MVN指令可完成從另外一個寄存器、被移位的寄存器、或將一個當即數加載到目的寄存器。與MOV指令不一樣之處是在傳送以前按位被取反了,即把一個被取反的值傳送到目的寄存器中。其中S決定指令的操做是否影響CPSR中條件標誌位的值,當沒有S時指令不更新CPSR中條件標誌位的值。
如:
MVN R0,#0 ;將當即數0取反傳送到寄存器R0中,完成後R0=-1
三、 CMP指令
CMP指令的格式爲:
CMP{條件} 操做數1,操做數2
CMP指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數進行比較,同時更新CPSR中條件標誌位的值。該指令進行一次減法運算,但不存儲結果,只更改條件標誌位。標誌位表示的是操做數1與操做數2的關係(大、小、相等),例如,當操做數1大於操做操做數2,則此後的有GT 後綴的指令將能夠執行。
如:
CMP R1,R0 ;將寄存器R1的值與寄存器R0的值相減,並根據結果設置CPSR的標誌位
CMP R1,#100 ;將寄存器R1的值與當即數100相減,並根據結果設置CPSR的標誌位
四、 CMN指令
CMN指令的格式爲:
CMN{條件} 操做數1,操做數2
CMN指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數取反後進行比較,同時更新CPSR中條件標誌位的值。該指令實際完成操做數1和操做數2相加,並根據結果更改條件標誌位。
如:
CMN R1,R0 ;將寄存器R1的值與寄存器R0的值相加,並根據結果設置CPSR的標誌位
CMN R1,#100 ;將寄存器R1的值與當即數100相加,並根據結果設置CPSR的標誌位
五、 TST指令
TST指令的格式爲:
TST{條件} 操做數1,操做數2
TST指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數進行按位的與運算,並根據運算結果更新CPSR中條件標誌位的值。操做數1是要測試的數據,而操做數2是一個位掩碼,該指令通常用來檢測是否設置了特定的位。
如:
TST R1,#%1 ;用於測試在寄存器R1中是否設置了最低位(%表示二進制數)
TST R1,#0xffe ;將寄存器R1的值與當即數0xffe按位與,並根據結果設置CPSR的標誌位
六、 TEQ指令
TEQ指令的格式爲:
TEQ{條件} 操做數1,操做數2
TEQ指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數進行按位的異或運算,並根據運算結果更新CPSR中條件標誌位的值。該指令一般用於比較操做數1和操做數2是否相等。
如:
TEQ R1,R2 ;將寄存器R1的值與寄存器R2的值按位異或,並根據結果設置CPSR的標誌位
七、 ADD指令
ADD指令的格式爲:
ADD{條件}{S} 目的寄存器,操做數1,操做數2
ADD指令用於把兩個操做數相加,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。
如:
ADD R0,R1,R2 ; R0 = R1 + R2
ADD R0,R1,#256 ; R0 = R1 + 256
ADD R0,R2,R3,LSL#1 ; R0 = R2 + (R3 << 1)
八、 ADC指令
ADC指令的格式爲:
ADC{條件}{S} 目的寄存器,操做數1,操做數2
ADC指令用於把兩個操做數相加,再加上CPSR中的C條件標誌位的值,並將結果存放到目的寄存器中。它使用一個進位標誌位,這樣就能夠作比32位大的數的加法,注意不要忘記設置S後綴來更改進位標誌。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。
如下指令序列完成兩個128位數的加法,第一個數由高到低存放在寄存器R7~R4,第二個數由高到低存放在寄存器R11~R8,運算結果由高到低存放在寄存器R3~R0:
ADDS R0,R4,R8 ; 加低端的字
ADCS R1,R5,R9 ; 加第二個字,帶進位
ADCS R2,R6,R10 ; 加第三個字,帶進位
ADC R3,R7,R11 ; 加第四個字,帶進位
九、 SUB指令
SUB指令的格式爲:
SUB{條件}{S} 目的寄存器,操做數1,操做數2
SUB指令用於把操做數1減去操做數2,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令可用於有符號數或無符號數的減法運算。
如:
SUB R0,R1,R2 ; R0 = R1 - R2
SUB R0,R1,#256 ; R0 = R1 - 256
SUB R0,R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)
十、SBC指令
SBC指令的格式爲:
SBC{條件}{S} 目的寄存器,操做數1,操做數2
SBC指令用於把操做數1減去操做數2,再減去CPSR中的C條件標誌位的反碼,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令使用進位標誌來表示借位,這樣就能夠作大於32位的減法,注意不要忘記設置S後綴來更改進位標誌。該指令可用於有符號數或無符號數的減法運算。
如:
SUBS R0,R1,R2 ; R0 = R1 - R2 - !C,並根據結果設置CPSR的進位標誌位
11、RSB指令
RSB指令的格式爲:
RSB{條件}{S} 目的寄存器,操做數1,操做數2
RSB指令稱爲逆向減法指令,用於把操做數2減去操做數1,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令可用於有符號數或無符號數的減法運算。
如:
RSB R0,R1,R2 ; R0 = R2 – R1
RSB R0,R1,#256 ; R0 = 256 – R1
RSB R0,R2,R3,LSL#1 ; R0 = (R3 << 1) - R2
十二、RSC指令
RSC指令的格式爲:
RSC{條件}{S} 目的寄存器,操做數1,操做數2
RSC指令用於把操做數2減去操做數1,再減去CPSR中的C條件標誌位的反碼,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令使用進位標誌來表示借位,這樣就能夠作大於32位的減法,注意不要忘記設置S後綴來更改進位標誌。該指令可用於有符號數或無符號數的減法運算。
如:
RSC R0,R1,R2 ; R0 = R2 – R1 - !C
1三、AND指令
AND指令的格式爲:
AND{條件}{S} 目的寄存器,操做數1,操做數2
AND指令用於在兩個操做數上進行邏輯與運算,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令經常使用於屏蔽操做數1的某些位。
如:
AND R0,R0,#3 ; 該指令保持R0的0、1位,其他位清零。
1四、ORR指令
ORR指令的格式爲:
ORR{條件}{S} 目的寄存器,操做數1,操做數2
ORR指令用於在兩個操做數上進行邏輯或運算,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令經常使用於設置操做數1的某些位。
如:
ORR R0,R0,#3 ; 該指令設置R0的0、1位,其他位保持不變。
1五、EOR指令
EOR指令的格式爲:
EOR{條件}{S} 目的寄存器,操做數1,操做數2
EOR指令用於在兩個操做數上進行邏輯異或運算,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令經常使用於反轉操做數1的某些位。
如:
EOR R0,R0,#3 ; 該指令反轉R0的0、1位,其他位保持不變。
1六、BIC指令
BIC指令的格式爲:
BIC{條件}{S} 目的寄存器,操做數1,操做數2
BIC指令用於清除操做數1的某些位,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。操做數2爲32位的掩碼,若是在掩碼中設置了某一位,則清除這一位。未設置的掩碼位保持不變。
如:
BIC R0,R0,#%1011 ; 該指令清除 R0 中的位 0、1、和 3,其他的位保持不變。
ARM微處理器支持的乘法指令與乘加指令共有6條,可分爲運算結果爲32位和運算結果爲64位兩類。與前面的數據處理指令不一樣,指令中的所有操做數、目的寄存器必須爲通用寄存器,不能對操做數使用當即數或被移位的寄存器,同時,目的寄存器和操做數1必須是不一樣的寄存器。
一、 MUL指令
MUL指令的格式爲:
MUL{條件}{S} 目的寄存器,操做數1,操做數2
MUL指令完成將操做數1與操做數2的乘法運算,並把結果放置到目的寄存器中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數或無符號數。
如:
MUL R0,R1,R2 ;R0 = R1 × R2
MULS R0,R1,R2 ;R0 = R1 × R2,同時設置CPSR中的相關條件標誌位
二、 MLA指令
MLA指令的格式爲:
MLA{條件}{S} 目的寄存器,操做數1,操做數2,操做數3
MLA指令完成將操做數1與操做數2的乘法運算,再將乘積加上操做數3,並把結果放置到目的寄存器中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數或無符號數。
如:
MLA R0,R1,R2,R3 ;R0 = R1 × R2 + R3
MLAS R0,R1,R2,R3 ;R0 = R1 × R2 + R3,同時設置CPSR中的相關條件標誌位
三、 SMULL指令
SMULL指令的格式爲:
SMULL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
SMULL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位放置到目的寄存器Low中,結果的高32位放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數。
如:
SMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
四、 SMLAL指令
SMLAL指令的格式爲:
SMLAL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
SMLAL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位同目的寄存器Low中的值相加後又放置到目的寄存器Low中,結果的高32位同目的寄存器High中的值相加後又放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數。
對於目的寄存器Low,在指令執行前存放64位加數的低32位,指令執行後存放結果的低32位。
對於目的寄存器High,在指令執行前存放64位加數的高32位,指令執行後存放結果的高32位。
如:
SMLAL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1
五、 UMULL指令
UMULL指令的格式爲:
UMULL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
UMULL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位放置到目的寄存器Low中,結果的高32位放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的無符號數。
如:
UMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
六、 UMLAL指令
UMLAL指令的格式爲:
UMLAL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
UMLAL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位同目的寄存器Low中的值相加後又放置到目的寄存器Low中,結果的高32位同目的寄存器High中的值相加後又放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的無符號數。
對於目的寄存器Low,在指令執行前存放64位加數的低32位,指令執行後存放結果的低32位。
對於目的寄存器High,在指令執行前存放64位加數的高32位,指令執行後存放結果的高32位。
如:
UMLAL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1
跳轉指令用於實現程序流程的跳轉,在ARM程序中有兩種方法能夠實現程序流程的跳轉:使用專門的跳轉指令、直接向程序計數器PC寫入跳轉地址值。
直接向PC寫入跳轉地址值,能夠實如今4GB的地址空間中任意跳轉,在跳轉以前結合使用MOV LR,PC等相似指令,能夠保存未來的返回地址值,從而實如今4GB連續的線性地址空間的子程序調用。
使用跳轉指令能夠完成從當前指令向前或向後的32MB的地址空間的跳轉。
一、 B指令
B指令的格式爲:
B{條件} 目標地址
B指令是最簡單的跳轉指令。一旦遇到一個 B 指令,ARM 處理器將當即跳轉到給定的目標地址,從那裏繼續執行。注意存儲在跳轉指令中的實際值是相對當前PC值的一個偏移量,而不是一個絕對地址,它的值由彙編器來計算(參考尋址方式中的相對尋址)。它是 24 位有符號數,左移兩位後有符號擴展爲 32 位,表示的有效偏移爲 26 位(先後32MB的地址空間)。
如:
B Label ;程序無條件跳轉到標號Label處執行
CMP R1,#0 ;當CPSR寄存器中的Z條件碼置位時,程序跳轉到標號Label處執行
BEQ Label
二、 BL指令
BL指令的格式爲:
BL{條件} 目標地址
BL 是另外一個跳轉指令,但跳轉以前,會在寄存器R14中保存PC的當前內容,所以,能夠經過將R14 的內容從新加載到PC中,來返回到跳轉指令以後的那個指令處執行。該指令是實現子程序調用的一個基本但經常使用的手段。
如:
BL Label ;當程序無條件跳轉到標號Label處執行時,同時將當前的PC值保存到R14中
Label標號處能夠是一個子程序,在子程序的最後能夠使用MOV PC,LR指令跳回BL Label指令處的下一條指令繼續執行。
三、 BLX指令
BLX指令的格式爲:
BLX 目標地址
BLX指令從ARM指令集跳轉到指令中所指定的目標地址,並將處理器的工做狀態由ARM狀態切換到Thumb狀態,該指令同時將PC的當前內容保存到寄存器R14中。所以,當子程序使用Thumb指令集,而調用者使用ARM指令集時,能夠經過BLX指令實現子程序的調用和處理器工做狀態的切換。同時,子程序的返回能夠經過將寄存器R14值複製到PC中來完成。
四、 BX指令
BX指令的格式爲:
BX{條件} 目標地址
BX指令跳轉到指令中所指定的目標地址,目標地址處的指令既能夠是ARM指令,也能夠是Thumb指令。
ARM指令不容許直接操做程序狀態寄存器CPSR和SPSR。能夠經過程序狀態寄存器訪問指令,在程序狀態寄存器和通用寄存器之間傳送數據,而後在通用寄存器中進行處理。
一、 MRS指令
MRS指令的格式爲:
MRS{條件} 通用寄存器,程序狀態寄存器(CPSR或SPSR)
MRS指令用於將程序狀態寄存器的內容傳送到通用寄存器中。該指令通常用在如下幾種狀況:
1) 當須要改變程序狀態寄存器的內容時,可用MRS將程序狀態寄存器的內容讀入通用寄存器,修改後再寫回程序狀態寄存器。
2) 當在異常處理或進程切換時,須要保存程序狀態寄存器的值,可先用該指令讀出程序狀態寄存器的值,而後保存。
如:
MRS R0,CPSR ;傳送CPSR的內容到R0
MRS R0,SPSR ;傳送SPSR的內容到R0
二、 MSR指令
MSR指令的格式爲:
MSR{條件} 程序狀態寄存器(CPSR或SPSR)_<域>,操做數
MSR指令用於將操做數的內容傳送到程序狀態寄存器的特定域中。其中,操做數能夠爲通用寄存器或當即數。<域>用於設置程序狀態寄存器中須要操做的位,32位的程序狀態寄存器可分爲4個域:
位[31:24]爲條件標誌位域,用f表示;
位[23:16]爲狀態位域,用s表示;
位[15:8]爲擴展位域,用x表示;
位[7:0]爲控制位域,用c表示;
該指令一般用於恢復或改變程序狀態寄存器的內容,在使用時,通常要在MSR指令中指明將要操做的域。
如:
MSR CPSR,R0 ;傳送R0的內容到CPSR
MSR SPSR,R0 ;傳送R0的內容到SPSR
MSR CPSR_c,R0 ;傳送R0的內容到SPSR,但僅僅修改CPSR中的控制位域
ARM微處理器可支持多達16個協處理器,用於各類協處理操做,在程序執行的過程當中,每一個協處理器只執行鍼對自身的協處理指令,忽略ARM處理器和其餘協處理器的指令。
ARM的協處理器指令主要用於ARM處理器初始化ARM協處理器的數據處理操做,以及在ARM處理器的寄存器和協處理器的寄存器之間傳送數據,和在ARM協處理器的寄存器和存儲器之間傳送數據。
一、CDP指令
CDP指令的格式爲:
CDP{條件} 協處理器編碼,協處理器操做碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操做碼2。
CDP指令用於ARM處理器通知ARM協處理器執行特定的操做,若協處理器不能成功完成特定的操做,則產生未定義指令異常。其中協處理器操做碼1和協處理器操做碼2爲協處理器將要執行的操做,目的寄存器和源寄存器均爲協處理器的寄存器,指令不涉及ARM處理器的寄存器和存儲器。
如:
CDP P3,2,C12,C10,C3,4 ;該指令完成協處理器P3的初始化
二、LDC指令
LDC指令的格式爲:
LDC{條件}{L} 協處理器編碼,目的寄存器,[源寄存器]
LDC指令用於將源寄存器所指向的存儲器中的字數據傳送到目的寄存器中,若協處理器不能成功完成傳送操做,則產生未定義指令異常。其中,{L}選項表示指令爲長讀取操做,如用於雙精度數據的傳輸。
如:
LDC P3,C4,[R0] ;將ARM處理器的寄存器R0所指向的存儲器中的字數據傳送到協處理器P3的寄存器C4中。
三、STC指令
STC指令的格式爲:
STC{條件}{L} 協處理器編碼,源寄存器,[目的寄存器]
STC指令用於將源寄存器中的字數據傳送到目的寄存器所指向的存儲器中,若協處理器不能成功完成傳送操做,則產生未定義指令異常。其中,{L}選項表示指令爲長讀取操做,如用於雙精度數據的傳輸。
如:
STC P3,C4,[R0] ;將協處理器P3的寄存器C4中的字數據傳送到ARM處理器的寄存器R0所指向的存儲器中。
四、MCR指令
MCR指令的格式爲:
MCR{條件} 協處理器編碼,協處理器操做碼1,源寄存器,目的寄存器1,目的寄存器2,協處理器操做碼2。
MCR指令用於將ARM處理器寄存器中的數據傳送到協處理器寄存器中,若協處理器不能成功完成操做,則產生未定義指令異常。其中協處理器操做碼1和協處理器操做碼2爲協處理器將要執行的操做,源寄存器爲ARM處理器的寄存器,目的寄存器1和目的寄存器2均爲協處理器的寄存器。
如:
MCR P3,3,R0,C4,C5,6 ;該指令將ARM處理器寄存器R0中的數據傳送到協處理器P3的寄存器C4和C5中。
五、MRC指令
MRC指令的格式爲:
MRC{條件} 協處理器編碼,協處理器操做碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操做碼2。
MRC指令用於將協處理器寄存器中的數據傳送到ARM處理器寄存器中,若協處理器不能成功完成操做,則產生未定義指令異常。其中協處理器操做碼1和協處理器操做碼2爲協處理器將要執行的操做,目的寄存器爲ARM處理器的寄存器,源寄存器1和源寄存器2均爲協處理器的寄存器。
如:
MRC P3,3,R0,C4,C5,6 ;該指令將協處理器P3的寄存器中的數據傳送到ARM處理器寄存器中。
一、SWI指令
SWI指令的格式爲:
SWI{條件} 24位的當即數
SWI指令用於產生軟件中斷,以便用戶程序能調用操做系統的系統例程。操做系統在SWI的異常處理程序中提供相應的系統服務,指令中24位的當即數指定用戶程序調用系統例程的類型,相關參數經過通用寄存器傳遞,當指令中24位的當即數被忽略時,用戶程序調用系統例程的類型由通用寄存器R0的內容決定,同時,參數經過其餘通用寄存器傳遞。
如:
SWI 0x02 ;該指令調用操做系統編號位02的系統例程。
二、BKPT指令
BKPT指令的格式爲:
BKPT 16位的當即數
BKPT指令產生軟件斷點中斷,可用於程序的調試。
爲兼容數據總線寬度爲16位的應用系統,ARM體系結構除了支持執行效率很高的32位ARM指令集之外,同時支持16位的Thumb指令集。Thumb指令集是ARM指令集的一個子集,容許指令編碼爲16位的長度。與等價的32位代碼相比較,Thumb指令集在保留32位代碼優點的同時,大大的節省了系統的存儲空間。
全部的Thumb指令都有對應的ARM指令,並且Thumb的編程模型也對應於ARM的編程模型,在應用程序的編寫過程當中,只要遵循必定調用的規則,Thumb子程序和ARM子程序就能夠互相調用。當處理器在執行ARM程序段時,稱ARM處理器處於ARM工做狀態,當處理器在執行Thumb程序段時,稱ARM處理器處於Thumb工做狀態。
與ARM指令集相比較,Thumb指令集中的數據處理指令的操做數仍然是32位,指令地址也爲32位,但Thumb指令集爲實現16位的指令長度,捨棄了ARM指令集的一些特性,如大多數的Thumb指令是無條件執行的,而幾乎全部的ARM指令都是有條件執行的;大多數的Thumb數據處理指令的目的寄存器與其中一個源寄存器相同。
因爲Thumb指令的長度爲16位,即只用ARM指令一半的位數來實現一樣的功能,因此,要實現特定的程序功能,所需的Thumb指令的條數較ARM指令多。在通常的狀況下,Thumb指令與ARM指令的時間效率和空間效率關係爲:
— Thumb代碼所需的存儲空間約爲ARM代碼的60%~70%
— Thumb代碼使用的指令數比ARM代碼多約30%~40%
— 若使用32位的存儲器,ARM代碼比Thumb代碼快約40%
— 若使用16位的存儲器,Thumb代碼比ARM代碼快約40%~50%
— 與ARM代碼相比較,使用Thumb代碼,存儲器的功耗會下降約30%
顯然,ARM指令集和Thumb指令集各有其優勢,若對系統的性能有較高要求,應使用32位的存儲系統和ARM指令集,若對系統的成本及功耗有較高要求,則應使用16位的存儲系統和Thumb指令集。固然,若二者結合使用,充分發揮其各自的優勢,會取得更好的效果。
ARM編譯器通常都支持彙編語言的程序設計和C/C++語言的程序設計,以及二者的混合編程。在ARM彙編語言程序裏,有一些特殊指令助記符,這些助記符與指令系統的助記符不一樣,沒有相對應的操做碼,一般稱這些特殊指令助記符爲僞指令,他們所完成的操做稱爲僞操做。僞指令在源程序中的做用是爲完成彙編程序做各類準備工做的,這些僞指令僅在彙編過程當中起做用,一旦彙編結束,僞指令的使命就完成。
在ARM的彙編程序中,有以下幾種僞指令:ARM僞指令、符號定義僞指令、數據定義僞指令、段定義僞指令、模塊控制僞指令、彙編控制僞指令、宏處理僞指令等等。
須要特別指出的是,除了幾條ARM僞指令之外,其它的僞指令依賴於編譯器。也就是說,不一樣的ARM編譯器的僞指令集是不相同的。例如,ADS編譯器的段定義僞指令爲AREA,而IAR編譯器的段定義僞指令爲RSEG和ASEG。這種狀況使得不一樣編譯器下編出的ARM彙編程序是不一樣的。讀者在閱讀不一樣學習材料時應注意分辨在不一樣編譯器下ARM彙編程序的區別。
本書介紹的是IAR EWARM編譯器支持的ARM彙編僞指令。
ARM僞指令不是ARM指令集中的指令。它能夠象其它ARM指令同樣使用,但在編譯時這些指令將被等效的ARM指令所取代。
一、LDR-大範圍地址讀取
LDR僞指令的格式爲:
LDR{條件} reg,=expr/label_expr
reg爲加載的目的寄存器;expr爲32位當即數;label_expr爲地址表達式或外部表達式。
LDR僞指令將32位常量或一個32位地址加載到指定寄存器。
如:
LDR R0,=#0x12345 ;加載32位當即數0x12345到寄存器R0
LDR R0,=DATA_BUF+60 ;加載DATA_BUF地址+60
二、ADR-小範圍地址讀取
ADR僞指令的格式爲:
ADR{條件} reg,expr
reg爲加載的目的寄存器;expr爲相對偏移表達式,非字對齊時取值範圍爲-255~255字節,字對齊時取值範圍爲-1020~1020字節。
ADR僞指令將基於當前PC相對偏移的地址值讀取到寄存器中。
如:
Start: MOV R0,#10
ADR R4,start ;至關於SUB R4,PC,#0x0c
三、ADRL-中範圍地址讀取
ADRL僞指令與ADR相似,不一樣在expr的取值範圍,非字對齊時取值範圍爲64KB,字對齊時取值範圍爲256KB。
四、NOP-空操做
一、DCB和DC8
該僞指令的格式爲:
標號 DCB或DC8 表達式
DCB和DC8僞指令用於分配一片連續的8位字節存儲單元,並用僞指令中指定的表達式初始化。其中表達式能夠爲0~255的數字或字符串。
如:
Str DCB 「This is a test!」 ;分配一個字符串,每一個字符8位字節
二、DCW和DC1六、DCD和DC32
與DCB和DC8用法相同,不一樣的是分別分配16位半字節單元和32位字單元。
三、DF32和DF64
分別表示32位的單精度浮點數和64位的雙精度浮點數。
四、DS八、DS1六、DS24和DS32
分別用於保留8位字節、16位半字、24位字和32位字的存儲器空間。
如:
Dataspace DS8 100 ;保留100個8位字節的存儲器空間
一、=、ALIAS和EQU
該僞指令的格式爲:
標號 = 表達式
標號 ALIAS 表達式
標號 EQU 表達式
僞指令EQU和=可用於爲程序模塊中的常量、標號等賦值,定義的局部符號僅在其所在的模塊內有效。僞指令ALIAS爲符號起個別名。定義的符號採用PUBLIC僞指令聲明其屬性可以使之被其它模塊引用,引用其它模塊內符號時必須採用EXTERN僞指令聲明其屬性。
如:
Test EQU 50 ;定義符號Test的值爲50
二、ASSIGN、SET、SETA和VAR
用法與EQU等相似,可用於定義一個變量符號。採用VAR定義的變量符號不能用PUBLIC聲明其屬性。
三、DEFINE
用於定義在整個程序文件內都有效的全局符號。該符號能夠被文件內的全部程序模塊引用,但不能在同一文件內從新定義。
四、LIMIT
該僞指令的格式爲:
LIMIT 表達式, 最小值, 最大值, 提示信息
用於檢查表達式的值是否位於給定範圍以內。若是表達式值的範圍超限,則輸出提示信息。
如:
Speed VAR 23 ;定義符號speed的值爲23
LIMIT speed,10,30,…speed out of range… ;檢查speed的值是否超限
五、EXTERN(或IMPORT)
該僞指令的格式爲:
EXTERN 符號,[符號]……
EXTERN僞指令用於通知彙編器,要使用的符號在其它源文件中定義,但要在當前源文件中引用。
如:
Name Start ;程序模塊Start
EXTERN Main ;告訴彙編器Main符號在其它源文件中定義
……
BL Main ;在本模塊中引用Main符號
END
六、PUBLIC(或EXPORT)
該僞指令的格式爲:
PUBLIC 符號,[符號]……
PUBLIC僞指令用於在程序中聲明一個全局符號,該符號可在其它文件中引用。
七、REQUIRE
PUBLIC僞指令用於將一個符號標記爲已經被引用。
一、ASEG和ASEGN
該僞指令的格式爲:
ASEG [起始地址[(對齊)]]
ASEGN 段名[:存儲器類型],地址
ASEG僞指令用於定義一個絕對段,並設置段的起始地址。不指定地址值時第一個段默認起始地址爲0,後續段地址依次遞增。ASEGN僞指令用於設置指定段的絕對起始地址,並容許規定段類型。存儲器類型能夠爲CODE(代碼段)、DATA(數據段)、STACK(堆棧段)。
如:
ASEG 0 ;定義一個絕對段,起始地址0
ASEGN CODE:CODE,0 ;定義一個名爲CODE的代碼段,起始地址0
二、RSEG
該僞指令的格式爲:
RSEG 段名[:存儲器類型][:(NO)ROOT|(NO)REORDER|SORT][(對齊)]
RSEG僞指令用於定義一個可重定位段,段的起始地址由彙編器臨時分配。單個模塊中最多可定義65536個可重定位段。
如:
RSEG CODE:CODE:ROOT(2) ;定義一個名爲CODE的可重定位代碼段,用戶權限爲ROOT(可讀寫),段內存儲器對齊方式爲4字節對齊
三、DATA
該僞指令的格式爲:
DATA 段名[:存儲器類型][(對齊)]
DATA僞指令能夠在代碼段內定義一個數據區。
如:
RSEG CODE:CODE:ROOT(2)
DATA
f1: DC32 subrtn
四、STACK
該僞指令的格式爲:
COMMON 段名[:存儲器類型][(對齊)]
STACK僞指令用於定義一個堆棧段,用做堆棧的存儲器地址從高向低變化,而用做可重定位段的存儲器地址是從低向高變化。
五、COMMON
該僞指令的格式爲:
COMMON 段名[:存儲器類型][(對齊)]
COMMON僞指令用於定義公共段,各源文件中同名的COMMON段共享同一段內存。它的典型應用是多個不一樣子程序共享一段數據存儲區。中斷向量表也可安排在COMMON段,以便容許從多個服務子程序訪問。
六、CODE16和CODE32
CODE16僞指令用於告訴彙編器,其後的指令序列爲16位的Thumb指令;CODE32僞指令用於告訴彙編器,其後的指令序列爲32位的ARM指令。所以,在使用ARM指令和Thumb指令混合編程的代碼中,可用這兩條僞指令進行切換。但須要注意的是,它們只通知彙編器其後指令的類型,並不能對處理器進行狀態切換。
七、ORG
該僞指令的格式爲:
ORG 地址表達式
ORG僞指令用於設置段的起始地址。地址表達式的計算結果應與當前段的類型保持一致,如在RSEG(可重定位段)中,不要使用「ORG 10」,由於10是一個絕對地址,而應當使用「ORG .+10」,表示當前段偏移量爲10的地址。另外,地址表達式中不能包括任何前向和外部引用。
八、ALIGNRAM和ALIGNROM
該僞指令的格式爲:
ALIGNRAM 對齊
ALIGNROM 對齊[,填充值]
用於設置存儲器地址邊界的對齊方式,「對齊」是一個值爲2~30的常數,並按22~30設定對齊地址。ALIGNRAM以數據增量方式對齊,ALIGNROM以填充0字節方式對齊。
九、EVEN和ODD
該僞指令的格式爲:
EVEN [填充值]
ODD [填充值]
EVEN僞指令用於將程序計數器PC以偶數地址對齊(等價於ALIGNROM 1),ODD僞指令用於將程序計數器PC以奇數地址對齊。
一、NAME和PROGRAM
該僞指令的格式爲:
NAME 模塊名
PROGRAM 模塊名
NAME和PROGRAM僞指令用於定義一個程序模塊。程序模塊相似於C語言中的函數,是程序中相對獨立的一個部分。程序模塊即便沒有被調用也會被無條件連接。
如:
NAME Main ;定義一個名爲Main的程序模塊
二、END和ENDMOD
END僞指令用於結束整個彙編語言程序,ENDMOD用於結束當前程序模塊。每一個彙編語言程序最後必須使用END僞指令通知彙編器已經到了源程序結尾,以結束彙編。
三、LIBRARY和MODULE
該僞指令用於定義多模塊文件中的小模塊,其中每一個小模塊表明一段子程序,從而能夠方便地建立庫模塊文件。與NAME和PROGRAM不一樣的是,用LIBRARY和MODULE定義的模塊只有在被調用時纔會複製到連接代碼中。
四、RTMODEL
該僞指令的格式爲:
RTMODEL 關鍵字字符串,值字符串
該僞指令用於聲明模塊的運行模式屬性,以強制模塊之間的一致性。全部能被連接在一塊兒的模塊必須具備相同的關鍵字;值字符串要麼具備相同的值,要麼其值爲星號「*」。
一、$和INCLUDE
該僞指令的格式爲:
$ 文件名
INCLUDE 文件名
該僞指令用於給當前源文件加載頭文件。
二、CASEOFF和CASEON
該僞指令用於源程序文件中禁止和容許大小寫字符敏感。
三、LTORG
在使用ARM僞指令LDR加載地址數據時,要在適當的位置加入LTORG聲明一個數據區,把要加載的數據保存在數據區內,再用LDR讀出數據。LTORG僞指令一般放在無條件分支或子程序返回指令後面,這樣處理器就不會錯誤的將數據區中的數據看成指令執行。
四、RADIX
該僞指令用於聲明當前使用的數制形式。如:
RADIX 16D ;聲明當前使用十六進制數
MOV R0,#12 ;此處#12爲0x12
五、IF、ELSE和ENDIF
該僞指令的格式爲:
IF 邏輯表達式
指令序列1
ELSE
指令序列2
ENDIF
條件彙編僞指令能根據設定條件的成立與否決定是否對指令序列進行彙編生成目標代碼。若邏輯表達式爲真,則對指令序列1彙編生成目標代碼;不然對指令序列2彙編。其中還能夠用ELSEIF僞指令設定新條件。
如:
DEFINE Test ;定義一個全局變量Test
……
IF Test = TRUE
指令序列1
ELSE
指令序列2
ENDIF
一、MACRO和ENDM
該僞指令的格式爲:
宏名 MACRO [,參數][ ,參數]……
指令序列
ENDM
MACRO僞指令用於定義一個宏,引用宏時必須使用定義的宏名,並可向宏中傳遞參數。ENDM僞指令用於結束宏定義。
如:
errmac MACRO text
BL abort
DATA
DC8 text,0
ENDM
包含在MACRO和ENDM之間的指令序列稱爲宏定義體。在宏定義體的第一行應聲明宏的原型(包括宏名和所需的參數),而後就能夠在彙編程序中經過宏名來調用該指令序列。在源程序被編譯時,彙編器將宏調用展開,用宏定義中的指令序列代替程序中的宏調用,並將實際參數值傳遞給宏定義中的形式參數。
二、REPT和ENDR
該僞指令的格式爲:
REPT 表達式
指令序列
ENDR
該僞指令用於指示彙編器將指定的指令序列進行重複彙編,重複次數由表達式的值肯定。若是表達式的值爲0,則不進行任何操做。
三、REPTC和ENDR
該僞指令的格式爲:
REPTC 符號,替換字符串
指令序列
ENDR
該僞指令用於在宏展開時用替換字符串中的單個字符逐次替換符號。
四、REPTI和ENDR
該僞指令的格式爲:
REPTI 符號,替換字符串[,替換字符串]……
指令序列
ENDR
該僞指令用於在宏展開時用整個替換字符串替換符號。
ARM(Thumb)彙編語言的語句格式爲:
[標號[:]] 指令或僞指令 操做數 [;註釋]
其中,方括號內的內容爲可選項。
標號頂格書寫時後面可不用冒號,非頂格書寫時後面必須用冒號。
標號前加一個問號「?」前綴,表示該標號爲外部標號,且僅能經過彙編語言訪問;標號前加兩個下劃線「__」前綴,表示該標號爲外部標號,能經過C語言和彙編語言訪問;沒有前綴的標號爲局部標號,僅能在本模塊內訪問。
IAR彙編器對大小寫字符敏感,通常指令和僞指令助記符使用大寫,標號使用大小寫混雜的方式以示區分。
同時,若是一條語句太長,可將該長語句分爲若干行來書寫,在行的末尾用「\」表示下一行與本行爲同一條語句。
IAR彙編器規定彙編語言程序文件的默認擴展名爲「.s79」,也能夠用「.s」或「.asm」做爲擴展名。
在彙編語言程序設計中,常用各類符號代替地址、變量和常量等,以增長程序的可讀性。儘管符號的命名由編程者決定,但並非任意的,必須遵循如下的約定:
1.符號由大小寫字母、數字及下劃線組成,符號不能用數字開頭。
2.符號區分大小寫,同名的大、小寫符號會被編譯器認爲是兩個不一樣的符號。
3.符號在其做用範圍內必須惟一。
4.自定義的符號名不能與系統的保留字相同。
5.符號名不該與指令或僞指令同名。
6. IAR彙編器內部預約義符號以雙下劃線開頭和結尾。如:__IAR_SYSTEMS_ASM__。
一、 常量
程序中的常量是指其值在程序的運行過程當中不能被改變的量。ARM(Thumb)彙編程序所支持的常量有數字常量、邏輯常量和字符串常量。
數字常量通常爲32位的整數,看成爲無符號數時,其取值範圍爲0~232-1,看成爲有符號數時,其取值範圍爲-231~231-1。數字常量有4種表示形式:十進制數如123、-456等;十六進制數如0x123、0FFFFH等;八進制數如1234q等;二進制數如1010b等。
邏輯常量只有兩種取值狀況:TRUE和FALSE。
字符串常量爲一個固定的字符串,通常用於程序運行時的信息提示。用法與標準C語言相同。
二、 變量
程序中的變量是指其值在程序的運行過程當中能夠改變的量。ARM(Thumb)彙編程序所支持的變量有數字變量、邏輯變量和字符串變量。
數字變量用於在程序的運行中保存數字值,但注意數字值的大小不該超出數字變量所能表示的範圍。
邏輯變量用於在程序的運行中保存邏輯值,邏輯值只有兩種取值狀況:真或假。
字符串變量用於在程序的運行中保存一個字符串,但注意字符串的長度不該超出字符串變量所能表示的範圍。
在ARM(Thumb)彙編語言程序中,以程序段爲單位組織代碼。段是相對獨立的指令或數據序列,具備特定的名稱。段能夠分爲代碼段和數據段,代碼段的內容爲執行代碼,數據段存放代碼運行時須要用到的數據。一個彙編程序至少應該有一個代碼段,當程序較長時,能夠分割爲多個代碼段和數據段,多個段在程序編譯連接時最終造成一個可執行的映象文件。
可執行映象文件一般由如下幾部分構成:
1. 1個或多個代碼段,代碼段的屬性爲只讀。
2. 0個或多個包含初始化數據的數據段,數據段的屬性爲可讀寫。
3. 0個或多個不包含初始化數據的數據段,數據段的屬性爲可讀寫。
連接器根據系統默認或用戶設定的規則,將各個段安排在存儲器中的相應位置。所以源程序中段之間的相對位置與可執行的映象文件中段的相對位置通常不會相同。
如下是一個彙編語言源程序的基本結構:
代碼清單3.1
NAME ASM_EXAMPL ;定義一個名爲ARM_EXAMPL的程序模塊
RSEG CODE:CODE:ROOT(2) ;定義一個可重定位的代碼段
CODE32 ;執行32位ARM指令
ORG 0x1000 ;定義程序起始地址爲0x1000
Start: LDR R0,=0x3FF5000 ;Start處的地址即爲0x1000
LDR R1,=0xff
STR R1,[R0]
MOV R0,#0x10
MOV R1,#0x20
ADD R0,R0,R1
Stop: B Stop ;跳轉到指令自己,程序中止運行
ENDMOD ;本程序模塊結束
END ;本程序結束
程序很簡單,它完成的功能並不重要,但它已經表示出了一個ARM彙編語言程序的基本結構。
程序設計中的三種基本結構是:順序結構、分支結構和循環結構。在C語言中能夠使用if-else語句實現單分支和雙分支結構,也能夠經過switch-case語句實現多分支結構。可是在彙編語言中,分支結構通常是經過跳轉指令結合標號來實現的。
在ARM彙編語言程序中,因爲ARM指令支持條件執行,從而大大減小了分支程序的複雜程度。
例如:用兩個整數展轉相減的方法求它們的最大公約數。注意體會B指令加條件碼的執行方式。程序中使用的main標號是由於IAR彙編器通常默認從main標號處開始執行。
代碼清單3.2
NAME GCD
PUBLIC main ;聲明外部引用標號main
B main ;從main標號處開始執行
RSEG CODE:CODE
CODE32
main: MOV R0,#120
MOV R1,#96
Gcd: CMP R0,R1 ;比較兩數的大小
BEQ Stop ;若是兩數相等則跳到結束處
BLT Less ;若是R0<R1則跳到Less標號處
SUB R0,R0,R1 ;不然R0=R0-R1
B Gcd
Less: SUB R1,R1,R0 ;R1=R1-R0
B Gcd
Stop: B Stop ;跳轉到指令自己,程序中止運行
ENDMOD ;本程序模塊結束
END ;本程序結束
經過跳轉指令還能夠實現程序的循環結構。
例如:求n=1+2+…+10累加的和。
代碼清單3.3
NAME SUM
PUBLIC main
B main
RSEG CODE
CODE32
main: MOV R0,#10
MOV R1,R0 ;利用R1寄存器作循環計數器
Loop: SUBS R1,R1,1 ;循環次數減1
ADD R0,R0,R1
BNE Loop ;循環次數爲0則結束循環
Stop: B Stop
ENDMOD
END
經過BL指令能夠實現子程序調用,語法:BL子程序名。
在子程序的結束處,能夠經過MOV PC,LR返回到主程序中。一般能夠使用寄存器R0~R3完成傳遞參數到子程序和從子程序返回運算的結果。
如下是使用BL指令調用子程序的彙編語言源程序的例子,該程序編寫了一個在內存裏拷貝字符串的子程序,而後在主程序裏調用它。
代碼清單3.4
NAME STRCPY
PUBLIC main
B main
RSEG CODE
CODE32
main: LDR R1,=srcstr ;R1指向源字符串
LDR R0,=dststr ;R0指向目標字符串
BL strcopy ;調用strcopy子程序
stop: B stop ;程序中止
strcopy: ;子程序定義
LDRB R2,[R1],#1 ;讀一個字符到R2,並更新源字符地址
STRB R2,[R0],#1 ;寫一個字符,並更新目的字符地址
CMP R2,#0 ;是否結束。以數字0爲標誌
BNE strcopy ;循環執行
DATA ;數據區
srcstr DCB "First string - source ",0
dststr DCB "Second string - destination ",0
ENDMOD
END
查表法是編程中經常使用的一種技巧。當程序涉及到較多的數據、數據串或數據表格時,能夠經過地址來對它們進行訪問。一般有兩種方法裝載地址:(1)經過ADR和ADRL僞指令直接裝載地址;(2)經過僞指令LDR Rd,=Label從數據表格中裝載地址。
下面的程序設置了3個參數,arithfunc根據3個參數返回一個R0值。當R0=0時,R0=R1+R2;當R0=1時,R0=R1-R2;當R0>1時,R0=R1+R2。:
代碼清單3.5
NAME JUMP
PUBLIC main
B main
Num EQU 2 ;跳轉表格的入口數
RSEG CODE
CODE32
main: MOV R0,#0 ;如下設置3個參數
MOV R1,#3
MOV R2,#2
BL arithfunc ;調用子程序
stop: B stop ;程序中止
arithfunc:
CMP R0,#Num ;比較參數
BHS Doadd ;若R0>=2,則執行加法
ADR R3,jumptable ;裝載跳轉表格標號地址
LDR PC,[R3,R0,LSL #2] ;跳到相應子程序入口地址處
Jumptable:
DCD Doadd ;Doadd子程序的入口地址
DCD Dosub ;Dosub子程序的入口地址
Doadd: ADD R0,R1,R2 ;=0或>1時執行的操做
MOV PC,LR
Dosub: SUB R0,R1,R2 ;=1時執行的操做
MOV PC,LR
ENDMOD
END
在應用系統的程序設計中,若全部的編程任務均用匯編語言來完成,其工做量是可想而知的,同時,不利於系統升級或應用軟件移植,事實上,ARM體系結構支持C/C+以及與彙編語言的混合編程,在一個完整的程序設計的中,除了初始化部分用匯編語言完成之外,其主要的編程任務通常都用C/C++ 完成。
彙編語言與C/C++的混合編程一般有如下幾種方式:
1. 在C/C++代碼中嵌入彙編指令。
在ARM C中,能夠使用關鍵字__arm來標識一段彙編指令程序。格式以下:
__asm
{
彙編指令序列
}
便可在C語言源程序中直接執行ARM彙編指令。
2. 在彙編程序和C/C++的程序之間進行變量的互訪。
3. 彙編程序、C/C++程序間的相互調用。
能夠把彙編程序和C/C++程序中須要共享的變量或函數用PUBLIC或extern關鍵字分別聲明爲全局變量或全局函數,而後在其它程序文件中便可進行訪問和調用。可是從好的編程風格來講,最好儘可能減小全局變量和全局函數的使用。
混合編程中,必須遵照必定的調用規則,如物理寄存器的使用、參數的傳遞等。ARM專門爲此制定了一個標準ATPCS(ARM-Thumb Procedure Call Standard,ARM-Thumb過程調用標準)。對於初學者來講,這是很是煩瑣的,在實際工做中也沒有太多必要。
在實際的編程應用中,使用較多的方式是:系統程序的初始化部分用匯編語言完成,而後用C/C++完成主要的編程任務,程序在執行時首先完成初始化過程,而後跳轉到C/C++程序代碼中。彙編程序和C/C++程序之間通常沒有參數的傳遞,也沒有頻繁的相互調用,所以,整個程序的結構顯得相對簡單,容易理解。
如下是一個這種結構程序的基本示例。該程序很是簡單,創建一個工程asm_c.eww,工程中包括一個彙編語言程序文件init.s79和一個C語言程序文件hello.c。
代碼清單3.6——init.s79文件
NAME INIT
PUBLIC main
EXTERN Main ;聲明引入C程序的Main()函數
B main
RSEG CODE
CODE32
main:
NOP ;此處能夠插入用戶本身編寫的系統初始化代碼
B Main ;轉向C語言程序
ENDMOD
END
代碼清單3.7——hello.c文件:
#include <stdio.h>
/*注意此處C語言程序的入口函數是大小寫敏感的Main()函數,而不是經常使用的main()函數。這是爲了跟彙編程序中的main入口區別開,以避免形成工程有兩個程序入口。*/
int Main(void)
{
printf("Hello, world!\n");
}
基於ARM內核的芯片多數爲複雜的片上系統,這種複雜系統裏的多數硬件模塊都是能夠配置的,須要由軟件來設置其須要的工做狀態。因爲C語言具備模塊性和可移植性的特色,大部分基於ARM的應用系統程序都採用C語言編寫。可是當系統復位啓動時,在進入C語言的main函數以前,須要有一段啓動程序來完成對存儲器配置、地址重映射和ARM芯片內部集成外圍功能初始化等工做。這類工做直接面對處理器內核和硬件控制器進行編程,用C語言較難實現,所以通常採用彙編語言編寫。
ARM內核的處理器在復位後,從0x00000000地址處開始讀取指令。實現啓動最簡單的方法是將應用程序放在映射空間地址爲0的ROM中。這樣當執行第1條指令時,應用程序就從0x00000000處開始執行。但這種方法有不少缺點:ROM的存儲寬度較小且速度較慢,會下降系統啓動和處理器對異常處理的速度;異常向量表放在ROM中,程序將沒法修改向量表,所以常將地址爲0的空間映射成RAM,但RAM中的程序掉電沒法保存,所以必須將ROM映射爲0地址,以保證有效的復位向量,而後再使用重映射命令將RAM映射爲0地址,ROM映射到其餘地址空間,並將異常向量從ROM複製到RAM中。
編寫啓動程序應遵循如下通常規則:
1. 設置入口指針
啓動程序首先必須定義入口指針,並且整個應用程序只有一個入口指針,一般應用程序的入口地址爲0。
2. 設置異常向量
基於ARM7TDMI內核的處理器共支持7種異常,異常處理地址存放在地址0處的異常向量表中,共8×4字節的空間。異常向量表的內容參見2.4.2節。
異常向量表一般放在存儲器底部,每一個異常分配4個字節的空間。每一個向量入口包含一條跳轉指令或加載PC的指令,以執行適當的轉移到具體的異常處理程序。若是ROM定位於0地址,則向量表由一系列固定的用以指向每一個異常的指令組成;不然向量必須被動態初始化。能夠在啓動程序中添加一段代碼,使其在運行時將向量表拷貝到0地址開始的存儲器空間。對於沒有使用的異常,使其指向一個只含返回指令的啞函數,以防止錯誤異常引發系統混亂。
3. 初始化片內集成外圍功能
因爲ARM公司僅設計內核並出售給其它半導體廠商,不一樣的廠商購買內核受權後加入本身的外圍功能,從而致使ARM核處理器芯片豐富多樣,但也使得不一樣芯片的啓動代碼在這一部分差異很大。編寫這一部分時應根據芯片和應用系統要求對它們進行合適的初始化。比較重要的操做通常有:外部總線接口的初始化、配置時鐘鎖相環、配置中斷控制器、禁用看門狗電路等。
4. 初始化存儲系統
有些ARM核芯片可經過對寄存器編程來初始化系統存儲器,而對於較複雜系統一般由存儲管理單元MMU來管理內存空間。爲正確運行應用程序,在初始化期間應將系統須要讀寫的數據和變量從ROM拷貝到RAM中;一些要求快速響應的程序,例如中斷處理程序,也須要在RAM中運行;若是使用Flash,對Flash的擦除和寫入操做也必定要在RAM中運行。
5. 初始化堆棧寄存器
系統堆棧初始化取決於用戶使用了哪些中斷,以及系統須要處理哪些錯誤類型。通常來講管理模式堆棧必須初始化。若是使用IRQ中斷,則IRQ堆棧必須初始化,而且必須在容許中斷以前進行。若是使用FIQ中斷,則FIQ堆棧也必須初始化,而且必須在容許中斷以前進行。通常在簡單的嵌入式系統中不使用停止狀態堆棧和未定義指令堆棧,但爲了調試方便仍是將其初始化。若是系統使用DRAM或其它外設,還須要設置相關寄存器,以肯定其刷新頻率、數據總線寬度等信息。
6. 改變處理器模式和狀態
此時能夠經過清除CPSR寄存器中的中斷控制位來容許中斷,這裏是安全開啓中斷的最先地方。這個階段處理器仍處於管理模式下。若是程序須要在用戶模式下運行,能夠在此處切換到用戶模式並初始化用戶模式堆棧指針。
7. 跳轉到C語言主程序
在從啓動程序跳轉到C語言程序的main函數以前,還須要初始化數據存儲空間。一般是加入一段循環代碼對數據存儲空間清0。這樣作的主要緣由是C語言中沒有初值的變量默認值均爲0。已經初始化變量的初值必須從ROM中複製到RAM中,其它變量的初值必須爲0。
下面給出了IAR EWARM軟件包提供的通常啓動程序代碼,實際應用中能夠根據具體芯片及應用系統要求進行適當修改,以適應不一樣場合的須要。
代碼清單3.8——IAR EWARM啓動代碼
;-----------------------------------------------------------------------------
; 文件中標號的命名規則:
; ?xxx - 僅能由彙編語言訪問的外部標號
; __xxx - 可由C語言訪問或定義的外部標號
; xxx - 單個模塊中的局部標號(注意,本文件包含多個模塊)
; main - 用戶程序的起點
;---------------------------------------------------------------
; 適用於整個文件的宏和模式定義
;---------------------------------------------------------------
; 模式,對應於CPSR寄存器的0~5位
MODE_BITS DEFINE 0x1F ; 用於CPSR模式的位屏蔽
USR_MODE DEFINE 0x10 ; 用戶模式
FIQ_MODE DEFINE 0x11 ; FIQ模式
IRQ_MODE DEFINE 0x12 ; IRQ模式
SVC_MODE DEFINE 0x13 ; 管理模式
ABT_MODE DEFINE 0x17 ; 停止模式
UND_MODE DEFINE 0x1B ; 未定義指令模式
SYS_MODE DEFINE 0x1F ; 系統模式
;---------------------------------------------------------------
; ?RESET
; 復位向量。一般INTVEC段被連接到地址0。爲程序調試方便,也能夠放在其它地址
;---------------------------------------------------------------
MODULE ?RESET
COMMON INTVEC:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; 復位後始終爲ARM模式
org 0x00
__program_start
ldr pc,[pc,#24] ; 絕對跳轉地址範圍爲4GB
; ldr b,?cstartup ; 相對跳轉容許重映射,限於32MB
; 能夠去掉如下指令前的註釋分號來容許異常向量
; 也能夠在C語言中採用預編譯命令「#pragma vector」
org 0x04
; ldr pc,[pc,#24] ; 跳轉到undef_handler
org 0x08
; ldr pc,[pc,#24] ; 跳轉到swi_handler
org 0x0c
; ldr pc,[pc,#24] ; 跳轉到prefetch_handler
org 0x10
; ldr pc,[pc,#24] ; 跳轉到data_handler
org 0x18
; ldr pc,[pc,#24] ; 跳轉到irq_handler
org 0x1c
; ldr pc,[pc,#24] ; 跳轉到fiq_handler
; 用於「ldr pc」指令的常數表入口定位於0x20
; 異常向量能夠用C語言的預編譯命令「#pragma vector」指定,也能夠
; 在如下dc32指令後面填入向量地址。向量地址爲ARM向量號+20
org 0x20
dc32 ?cstartup
org 0x24
; dc32 undef_handler
org 0x28
; dc32 swi_handler
org 0x2c
; dc32 prefetch_handler
org 0x30
; dc32 data_handler
org 0x38
; dc32 irq_handler
org 0x3c
; dc32 fiq_handler
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG ABT_STACK:DATA:NOROOT(2)
RSEG UND_STACK:DATA:NOROOT(2)
RSEG FIR_STACK:DATA:NOROOT(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; 從這裏開始執行
; 復位後爲ARM管理模式,禁止中斷
CODE32
?cstartup
; 須要時在這裏加入創建堆棧指針以前的初始化指令
; 初始化堆棧指針
; 如下方式可用於任何異常堆棧:FIQ, IRQ, SVC, ABT, UND, SYS.
; 用戶模式使用與SYS模式相同的堆棧
; 堆棧段必須在連接器命令文件中定義,而且已經在上面聲明
mrs r0,cpsr ; 原PSR值
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#IRQ_MODE ; 置IRQ模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(IRQ_STACK)&0xFFFFFFF8 ; IRQ_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#ABT_MODE ; 置Abort模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(ABT_STACK)&0xFFFFFFF8 ; ABT_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#SVC_MODE ; 置Supervisor模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(SVC_STACK) & 0xFFFFFFF8 ; SVC_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#UND_MODE ; 置Undefined模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(UND_STACK) & 0xFFFFFFF8 ; FIR_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#FIQ_MODE ; 置FIR模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(FIR_STACK) & 0xFFFFFFF8 ; FIR_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#SYS_MODE ; 置System模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; CSTACK結束
#ifdef __ARMVFP__
; 容許VFP協處理器
mov r0, #0x40000000 ; 置VFP的EN位
fmxr fpexc, r0 ; FPEXC, 清除其它
; 將緩衝區清0以禁止下溢出。爲知足IEEE 754標準,應刪除該指令並安裝合適的異常句柄
mov r0, #0x01000000 ; 置VFP的FZ位
fmxr fpscr, r0 ; FPSCR, 清除其它
#endif
; 在這裏能夠添加更多的用戶自定義初始化指令
; 跳轉到?main標號的地方,繼續IAR系統的啓動程序
ldr r0,=?main
bx r0
LTORG
ENDMOD
END
3.1 ARM7TDMI有幾種尋址方式?LDR R1,[R0,#0x04]屬於哪一種尋址方式?
3.2 ARM指令的條件碼有多少個?默認條件碼是什麼?
3.3 ARM指令中第二個操做數有哪幾種形式?
3.4 請指出MOV指令與LDR加載指令的區別及用途.
3.5 CMP指令的功能是什麼?寫一個程序,判斷R1的值是否大於0x30,是則將R1減去0x30。
3.6 調用子程序是用B仍是用BL指令?請寫出返回子程序的指令。
3.7 ARM狀態與Thumb狀態的切換指令是什麼?請舉例說明。
3.8 Thumb狀態與ARM狀態的寄存器有區別嗎?Thumb指令對哪些寄存器的訪問受到必定限制?
3.9 Thumb指令集的堆棧入棧、出棧指令是哪兩條?
3.10 把下面的C代碼轉換成彙編代碼。數組a和b分別存放在以0x4000和0x5000爲起始地址的存儲區內,類型爲long型(32位)。
for(i=0;i<8;i++)
{
a[i] = b[7-i];
}
3.11 編寫程序,將R1的高8位傳送到R2的低8位
3.12 編寫一段64位加法運算的程序,要求知足:[R1:R0]+[R3:R2],結果存入[R1:R0]中
3.13 編寫程序將地址0x0000 1000到0x0000 1030的數據所有搬遷到0x0000 2000到0x0000 2030的區域中,並將源數據區清零。
處理器的「體系結構」指從程序員角度觀察到的處理器的組織方式,因此又稱爲處理器的編程模型。其主要內容爲處理器內的寄存器組織、對存儲器的尋址方式、指令系統等。本章將介紹ARM7TDMI程序員模型、工做狀態與工做模式、ARM和Thumb狀態的寄存器組織、存儲器組織結構、異常及協處理器接口等一些基本概念。本章還要講述ARM的編程基礎,如ARM微處理器的基本工做原理、與程序設計相關的基本技術細節等。
LPC2400系列處理器包括LPC2468/LPC2470/LPC2478等多款芯片,是基於支持實時仿真和跟蹤的16/32位ARM7TDMI-S內核的微控制器,它與全部NXP LPC 2000處理器具備相同的存儲器映射、中斷向量控制、Flash編程和更新機制,以及調試和仿真功能。LPC2468/LPC2478的512KB大容量嵌入式高速Flash存儲器具備128位寬度的存儲器接口和獨特的加速結構,使得32位代碼可以在最高時鐘頻率72MHz下運行。16位Thumb模式能夠將代碼規模下降30%以上,而性能損失卻很小。LPC2470/LPC2478芯片內部還集成了LCD接口支持(最高1024×768像素、15階灰度單色和每像素24位真彩色TFT面板),使得這兩款芯片能夠普遍應用於各類手持式設備中。
LPC2400系列處理器擁有豐富的片上資源和外設接口。這一系列芯片的共同特性有:
-ARM7TDMI-S內核,最高72MHz主頻;
-98KB的片內靜態存儲器,其中64KB的片內SRAM,16KB SRAM用於以太網,16KB SRAM用於DMA控制器(也可用於USB控制器),2KB SRAM用於RTC實時時鐘;
-512KB片內Flash程序存儲器,片內Boot實現IAP和ISP片內Flash編程;
-可配置的外部存儲器接口,最多支持8個Bank,支持外部RAM、ROM和Flash存儲器擴展,每一個Bank最大可支持到256MB,可支持8/16/32位字寬;
-高級向量中斷控制器,支持32個向量中斷,可配置優先級和向量地址;
-通用AHB DMA控制器(GPDMA)能夠用於支持SSP、I2S和SD/MMC接口;
-10/100M以太網MAC接口;
-多個串行接口,包括4路UART、3路I2C串行總線接口和1個SPI接口;
-10位A/D和D/A轉換器,轉換時間低至2.44微秒;
-USB device/host/OTG接口;
-2個CAN總線接口;
-4個32位的定時器、2個PWM脈衝調製單元(每一個6路輸出)、實時時鐘和看門狗;
-160個高速GPIO端口(可承受5V電壓),4個獨立外部中斷引腳;
-標準ARM調試接口,兼容各類現有的調試工具;
-片內晶振頻率範圍1~24MHz;
-4個低功耗模式:空閒、睡眠、掉電和深度掉電模式;
-供電電壓3.3V(3.0V~3.6V)。
在LPC2400系列芯片中,LPC2468是LPC2478的無LCD控制器版本,LPC2470是LPC2478的無片內Flash版本,芯片的大多數特性是徹底相同的。因此在後面的章節中,本書一概採用LPC2478芯片爲例進行講解,請讀者在實際工做中注意具體芯片的差異。
LPC2400系列處理器包含一個支持仿真的ARM7TDMI-S CPU、與片內存儲器控制器接口的ARM7局部總線、與中斷控制器接口的AMBA高性能總線(AHB總線)和鏈接片內外設功能的AMBA外設總線(APB總線)。存儲模式爲小端模式。
AHB總線和APB總線都是ARM公司推出的AMBA片上總線規範的一部分。AHB(Advanced High performance Bus)系統總線主要用於高性能模塊(如CPU、DMA和DSP等)之間的鏈接,通常用於片內高性能高速度的外設,如:外部存儲器、USB接口、DMA控制器、以太網控制器、LCD液晶屏控制器以及高速GPIO控制器等。LPC2400中的AHB外設一共分配了2MB的地址範圍,它位於4GB ARM存儲器空間的最頂端。每一個AHB外設都分配了16KB的地址空間。
LPC2400的外設功能模塊都鏈接到APB總線。APB(Advanced Peripheral Bus)外圍總線主要用於低帶寬的周邊外設之間的鏈接,如:UART、I2C、SPI、I2S、A/D、D/A、CAN等等。APB總線與AHB總線之間經過AHB到APB的橋相連。APB外設也分配了2MB的地址範圍,每一個APB外設在APB地址空間內都分配了16KB的地址空間。
片內外設與器件引腳的鏈接由引腳鏈接模塊控制。軟件能夠經過控制該模塊讓引腳與特定的片內外設相鏈接。
LPC2400的結構框圖如圖4.1所示。
圖4.1 LPC2400結構框圖
LPC2400系列處理器共有208個引腳,通常提供兩種封裝形式:LQFP208和TFBGA208。其管腳封裝如圖4.2所示。
LQFP208 FBGA208
圖4.2 LPC2400系列處理器管腳封裝圖
LQFP指封裝本體厚度爲1.4mm的薄型QFP(四側引腳扁平封裝quad flat package),它是一種表面貼裝型封裝,引腳從四個側面引出呈L型,每一個側面52個引腳,引腳號分別爲1~5二、53~10四、105~15六、157~208。FBGA是塑料封裝的BGA(Ball Grid Array Package),即球柵陣列封裝,其引腳都在芯片底部,用英文字母行和數字列標識。因爲LPC2400系列處理器在實際使用中更多使用QFP封裝,本節引腳介紹以QFP封裝爲準。
從功能上,LPC2400的208個引腳分爲P0口、P1口、P2口、P3口、P4口,以及電源、復位、晶振和其它管腳幾部分。下面對這幾個部分分別進行介紹。
1. P0口: P0口是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P0口管腳描述如表4.1所示。
表4.1 LPC2400的P0口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P0[0] |
94 |
I/O |
P0[0]:GPIO口 |
I |
RD1:CAN1接收器輸入 |
||
O |
TXD3:UART3發送輸出端 |
||
I/O |
SDA1:I2C1數據輸入/輸出 |
||
P0[1] |
96 |
I/O |
P0[1]:GPIO口 |
O |
TD1:CAN1發送器輸出 |
||
I |
RXD3:UART3接收輸入端 |
||
I/O |
SCL1:I2C1時鐘輸入/輸出 |
||
P0[2] |
202 |
I/O |
P0[2]:GPIO口 |
O |
TXD0:UART0發送輸出端 |
||
P0[3] |
204 |
I/O |
P0[3]:GPIO口 |
I |
RXD0:UART0接收輸入端 |
||
P0[4] |
168 |
I/O |
P0[4]:GPIO口 |
I/O |
I2SRX_CLK:I2S總線接收時鐘 |
||
I |
RD2:CAN2接收輸入端 |
||
I |
CAP2[0]:Timer2的捕獲輸入通道0 |
||
P0[5] |
166 |
I/O |
P0[5]:GPIO口 |
I/O |
I2SRX_WS:I2S總線接收字選擇 |
||
I |
TD2:CAN2發送輸出端 |
||
I |
CAP2[1]:Timer2的捕獲輸入通道1 |
||
P0[6] |
164 |
I/O |
P0[6]:GPIO口 |
I/O |
I2SRX_SDA:I2S總線數據接收 |
||
I/O |
SSEL1:SSP1從機選擇 |
||
O |
MAT2[0]:Timer2的匹配輸出通道0 |
||
P0[7] |
162 |
I/O |
P0[7]:GPIO口 |
I/O |
I2STX_CLK:I2S總線發送時鐘 |
||
I/O |
SCK1:SSP1串行時鐘 |
||
O |
MAT2[1]:Timer2的匹配輸出通道1 |
||
P0[8] |
160 |
I/O |
P0[8]:GPIO口 |
I/O |
I2STX_WS:I2S總線發送字選擇 |
||
I/O |
MISO1:SSP1主機輸入從機輸出 |
||
O |
MAT2[2]:Timer2的匹配輸出通道2 |
||
P0[9] |
158 |
I/O |
P0[9]:GPIO口 |
I/O |
I2STX_SDA:I2S總線數據發送 |
||
I/O |
MOSI1:SSP1主機輸出從機輸入 |
||
O |
MAT2[3]:Timer2的匹配輸出通道3 |
||
P0[10] |
98 |
I/O |
P0[10]:GPIO口 |
O |
TXD2:UART2發送輸出端 |
||
I/O |
SDA2:I2C2數據輸入/輸出 |
||
O |
MAT3[0]:Timer3的匹配輸出通道0 |
||
P0[11] |
100 |
I/O |
P0[11]:GPIO口 |
I |
RXD2:UART2接收輸入端 |
||
I/O |
SCL2:I2C2時鐘輸入/輸出 |
||
O |
MAT3[1]:Timer3的匹配輸出通道1 |
||
P0[12] |
41 |
I/O |
P0[12]:GPIO口 |
O |
USB_PPWR2:USB端口2端口電源使能 |
||
I/O |
MISO1:SSP1主機輸入從機輸出 |
||
I |
AD0[6]:A/D轉換器0輸入6 |
||
P0[13] |
45 |
I/O |
P0[13]:GPIO口 |
O |
USB_UP_LED2:USB端口2LED |
||
I/O |
MOSI1:SSP1主機輸出從機輸入 |
||
I |
AD0[7]:A/D轉換器0輸入7 |
||
P0[14] |
69 |
I/O |
P0[14]:GPIO口 |
O |
USB_HSTEN2:USB端口2主機使能 |
||
O |
USB_CONNECT2:USB端口2軟件鏈接控制 |
||
I/O |
SSEL1:SSP1從機選擇 |
||
P0[15] |
128 |
I/O |
P0[15]:GPIO口 |
O |
TXD1:UART1發送輸出端 |
||
I/O |
SCK0:SSP0串行時鐘 |
||
I/O |
SCK:SPI串行時鐘 |
||
P0[16] |
130 |
I/O |
P0[16]:GPIO口 |
I |
RXD1:UART1接收輸入端 |
||
I/O |
SSEL0:SSP0從機選擇 |
||
I/O |
SSEL:SPI從機選擇 |
||
P0[17] |
126 |
I/O |
P0[17]:GPIO口 |
I |
CTS1:UART1清除發送輸入端 |
||
I/O |
MISO0:SSP0主機輸入從機輸出 |
||
I/O |
MISO:SPI主機輸入從機輸出 |
||
P0[18] |
124 |
I/O |
P0[18]:GPIO口 |
I |
DCD1:UART1數據載波檢測輸入端 |
||
I/O |
MOSI0:SSP0主機輸出從機輸入 |
||
I/O |
MOSI:SPI主機輸出從機輸入 |
||
P0[19] |
122 |
I/O |
P0[19]:GPIO口 |
I |
DSR1:UART1數據設置就緒端 |
||
O |
MCICLK:SD/MMC接口時鐘輸出線 |
||
I/O |
SDA1:I2C1數據輸入/輸出 |
||
P0[20] |
120 |
I/O |
P0[20]:GPIO口 |
O |
DTR1:UART1數據終止就緒端 |
||
I/O |
MCICMD:SD/MMC接口命令線 |
||
I/O |
SCL1:I2C1時鐘輸入/輸出 |
||
P0[21] |
118 |
I/O |
P0[21]:GPIO口 |
I |
RI1:UART1鈴響指示輸入端 |
||
O |
MCIPWR:SD/MMC電源供應使能 |
||
I |
RD1:CAN1接收輸入端 |
||
P0[22] |
116 |
I/O |
P0[22]:GPIO口 |
O |
RTS1:UART1請求發送輸出端 |
||
I/O |
MCIDAT0:SD/MMC接口數據線0 |
||
O |
TD1:CAN1發送輸出端 |
||
P0[23] |
18 |
I/O |
P0[23]:GPIO口 |
I |
AD0[0]:A/D轉換器0輸入0 |
||
I/O |
I2SRX_CLK:I2S總線接收時鐘 |
||
I |
CAP3[0]:Timer3的捕獲輸入通道0 |
||
P0[24] |
16 |
I/O |
P0[24]:GPIO口 |
I |
AD0[1]:A/D轉換器0輸入1 |
||
I/O |
I2SRX_WS:I2S總線字選擇 |
||
I |
CAP3[1]:Timer3的捕獲輸入通道1 |
||
P0[25] |
14 |
I/O |
P0[25]:GPIO口 |
I |
AD0[2]:A/D轉換器0輸入2 |
||
I/O |
I2SRX_SDA:I2S總線數據接收 |
||
O |
TXD3:UART3發送輸出端 |
||
P0[26] |
12 |
I/O |
P0[26]:GPIO口 |
I |
AD0[3]:A/D轉換器0輸入3 |
||
O |
AOUT:D/A轉換器輸出 |
||
I |
RXD3:UART3接收輸入端 |
||
P0[27] |
50 |
I/O |
P0[27]:GPIO口 |
I/O |
SDA0:I2C0數據輸入/輸出 |
||
P0[28] |
48 |
I/O |
P0[28]:GPIO口 |
I/O |
SCL0:I2C0時鐘輸入/輸出 |
||
P0[29] |
61 |
I/O |
P0[29]:GPIO口 |
I/O |
USB_D+1:USB端口1雙向D+線 |
||
P0[30] |
62 |
I/O |
P0[30]:GPIO口 |
I/O |
USB_D-1:USB端口1雙向D-線 |
||
P0[31] |
51 |
I/O |
P0[31]:GPIO口 |
I/O |
USB_D+2:USB端口2雙向D+線 |
2. P1口: P1口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P1口管腳描述如表4.2所示。
表4.2 LPC2400的P1口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P1[0] |
196 |
I/O |
P1[0]:GPIO口 |
O |
ENET_TXD0:以太網發送數據0(RMII/MII接口) |
||
P1[1] |
194 |
I/O |
P1[1]:GPIO口 |
O |
ENET_TXD1:以太網發送數據1(RMII/MII接口) |
||
P1[2] |
185 |
I/O |
P1[2]:GPIO口 |
O |
ENET_TXD2:以太網發送數據2(RMII/MII接口) |
||
O |
MCICLK:SD/MMC接口時鐘輸出線 |
||
O |
PWM0[1]:脈寬調製器0輸出1 |
||
P1[3] |
177 |
I/O |
P1[3]:GPIO口 |
O |
ENET_TXD3:以太網發送數據3(RMII/MII接口) |
||
O |
MCICMD:SD/MMC接口命令線 |
||
O |
PWM0[2]:脈寬調製器0輸出2 |
||
P1[4] |
192 |
I/O |
P1[4]:GPIO口 |
O |
ENET_TX_EN:以太網發送數據使能(RMII/MII接口) |
||
P1[5] |
156 |
I/O |
P1[5]:GPIO口 |
O |
ENET_TX_ER:以太網發送數據出錯(MII接口) |
||
O |
MCIPWR:SD/MMC電源供應使能 |
||
O |
PWM0[3]:脈寬調製器0輸出3 |
||
P1[6] |
171 |
I/O |
P1[6]:GPIO口 |
I |
ENET_TX_CLK:以太網發送時鐘(MII接口) |
||
I/O |
MCIDAT0:SD/MMC接口數據線0 |
||
O |
PWM0[4]:脈寬調製器0輸出4 |
||
P1[7] |
153 |
I/O |
P1[7]:GPIO口 |
I |
ENET_COL:以太網衝突檢測(MII接口) |
||
I/O |
MCIDAT1:SD/MMC接口數據線1 |
||
O |
PWM0[5]:脈寬調製器0輸出5 |
||
P1[8] |
190 |
I/O |
P1[8]:GPIO口 |
I |
ENET_CRS_DV/ENET_CRS:以太網載波檢測/數據有效(RMII接口)/以太網載波檢測(MII接口) |
||
P1[9] |
188 |
I/O |
P1[9]:GPIO口 |
I |
ENET_RXD0:以太網接收數據0(RMII/MII接口) |
||
P1[10] |
186 |
I/O |
P1[10]:GPIO口 |
I |
ENET_RXD1:以太網接收數據1(RMII/MII接口) |
||
P1[11] |
163 |
I/O |
P1[11]:GPIO口 |
I |
ENET_RXD2:以太網接收數據2(RMII/MII接口) |
||
I/O |
MCIDAT2:SD/MMC接口數據線2 |
||
O |
PWM0[6]:脈寬調製器0輸出6 |
||
P1[12] |
157 |
I/O |
P1[12]:GPIO口 |
I |
ENET_RXD3:以太網接收數據3(RMII/MII接口) |
||
I/O |
MCIDAT3:SD/MMC接口數據線3 |
||
I |
PCAP0[0]:脈寬調製器0捕獲輸入通道0 |
||
P1[13] |
147 |
I/O |
P1[13]:GPIO口 |
I |
ENET_RX_DV:以太網接收數據有效(MII接口) |
||
P1[14] |
184 |
I/O |
P1[14]:GPIO口 |
I |
ENET_RX_ER:以太網接收錯誤(MII接口) |
||
P1[15] |
182 |
I/O |
P1[15]:GPIO口 |
I |
ENET_REF_CLK/ENET_RX_CLK:以太網參考時鐘(RMII接口)/以太網接收時鐘(MII接口) |
||
P1[16] |
180 |
I/O |
P1[16]:GPIO口 |
I |
ENET_MDC:以太網MIIM時鐘 |
||
P1[17] |
178 |
I/O |
P1[17]:GPIO口 |
I/O |
ENET_MDIO:以太網MI數據輸入輸出 |
||
P1[18] |
66 |
I/O |
P1[18]:GPIO口 |
O |
USB_UP_LED1:USB端口1LED |
||
O |
PWM1[1]:脈寬調製器1輸出1 |
||
I |
CAP1[0]:Timer1捕獲輸入通道0 |
||
P1[19] |
68 |
I/O |
P1[19]:GPIO口 |
O |
USB_TX_E1:USB端口1發送使能信號(OTG收發器) |
||
O |
USB_PPWR1:USB端口1端口電源使能信號 |
||
I |
CAP1[1]:Timer1捕獲輸入通道1 |
||
P1[20] |
70 |
I/O |
P1[20]:GPIO口 |
O |
USB_TX_DP1:USB端口1D+數據發送(OTG收發器) |
||
O |
PWM1[2]:脈寬調製器1輸出2 |
||
I/O |
SCK0:SSP0串行時鐘 |
||
P1[21] |
72 |
I/O |
P1[21]:GPIO口 |
O |
USB_TX_DM1:USB端口1D-數據發送(OTG收發器) |
||
O |
PWM1[3]:脈寬調製器1輸出3 |
||
I/O |
SSEL0:SSP0從機選擇 |
||
P1[22] |
74 |
I/O |
P1[22]:GPIO口 |
I |
USB_RCV1:USB端口1差分數據接收(OTG收發器) |
||
I |
USB_PWRD1:USB端口1電源狀態(主機電源開關) |
||
O |
MAT1[0]:Timer1匹配輸出通道0 |
||
P1[23] |
76 |
I/O |
P1[23]:GPIO口 |
I |
USB_RX_DP1:USB端口1D+數據接收(OTG收發器) |
||
O |
PWM1[4]:脈寬調製器1輸出4 |
||
I/O |
MISO0:SSP0主機輸入從機輸出 |
||
P1[24] |
78 |
I/O |
P1[24]:GPIO口 |
I |
USB_RX_DM1:USB端口1D-數據接收(OTG收發器) |
||
O |
PWM1[5]:脈寬調製器1輸出5 |
||
I/O |
MOSI0:SSP0主機輸出從機輸入 |
||
P1[25] |
80 |
I/O |
P1[25]:GPIO口 |
O |
USB_LS1:USB端口1低速狀態(OTG收發器) |
||
O |
USB_HSTEN1:USB端口1主機使能狀態 |
||
O |
MAT1[1]:Timer1匹配輸出通道1 |
||
P1[26] |
82 |
I/O |
P1[26]:GPIO口 |
O |
USB_SSPND1:USB端口1總線懸掛狀態(OTG收發器) |
||
O |
PWM1[6]:脈寬調製器1輸出6 |
||
I |
CAP0[0]:Timer0捕獲輸入通道0 |
||
P1[27] |
88 |
I/O |
P1[27]:GPIO口 |
I |
USB_INT1:USB端口1OTG ATX中斷(OTG收發器) |
||
I |
USB_OVRCR1:USB端口1過流狀態 |
||
I |
CAP0[1]:Timer0捕獲輸入通道1 |
||
P1[28] |
90 |
I/O |
P1[28]:GPIO口 |
I/O |
USB_SCL1:USB端口1I2C串行時鐘(OTG收發器) |
||
I |
PCAP1[0]:脈寬調製器1捕獲輸入通道0 |
||
O |
MAT0[0]:Timer0匹配輸出通道0 |
||
P1[29] |
92 |
I/O |
P1[29]:GPIO口 |
I/O |
USB_SDA1:USB端口1I2C串行數據(OTG收發器) |
||
I |
PCAP1[1]:脈寬調製器1捕獲輸入通道1 |
||
O |
MAT0[1]:Timer0匹配輸出通道1 |
||
P1[30] |
42 |
I/O |
P1[30]:GPIO口 |
I |
USB_PWRD2:USB端口2電源狀態 |
||
I |
VBUS:指示USB總線當前電源。注意:當USB復位時這個信號必須爲高電平 |
||
I |
AD0[4]:A/D轉換器0輸入4 |
||
P1[31] |
40 |
I/O |
P1[31]:GPIO口 |
I |
USB_OVRCR2:USB端口2過流狀態 |
||
I/O |
SCK1:SSP1串行時鐘 |
||
I |
AD0[5]:A/D轉換器0輸入5 |
3. P2口: P2口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P2口管腳描述如表4.3所示。
表4.3 LPC2400的P2口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P2[0] |
154 |
I/O |
P2[0]:GPIO口 |
O |
PWM1[1]:脈寬調製器1輸出1 |
||
O |
TXD1:UART1發送輸出端 |
||
O |
TRACECLK/LCDPWR:跟蹤時鐘/LCD面板電源使能 |
||
P2[1] |
152 |
I/O |
P2[1]:GPIO口 |
O |
PWM1[2]:脈寬調製器1輸出2 |
||
I |
RXD1:UART1接收輸入端 |
||
O |
PIPESTAT0/LCDLE:流水線狀態位0/LCD行結束信號 |
||
P2[2] |
150 |
I/O |
P2[2]:GPIO口 |
O |
PWM1[3]:脈寬調製器1輸出3 |
||
I |
CTS1:UART1清除發送輸入端 |
||
O |
PIPESTAT1/LCDCP:流水線狀態位1/LCD面板時鐘 |
||
P2[3] |
144 |
I/O |
P2[3]:GPIO口 |
O |
PWM1[4]:脈寬調製器1輸出4 |
||
I |
DCD1:UART1數據載波檢測輸入端 |
||
O |
PIPESTAT2/LCDFP:流水線狀態位2/LCD幀脈衝(STN)垂直同步脈衝(TFT) |
||
P2[4] |
142 |
I/O |
P2[4]:GPIO口 |
O |
PWM1[5]:脈寬調製器1輸出5 |
||
I |
DSR1:UART1數據設置就緒端 |
||
O |
TRACESYNC/LCDAC:跟蹤同步/LCD交流斜線驅動(STN)數據使能輸出(TFT) |
||
P2[5] |
140 |
I/O |
P2[5]:GPIO口 |
O |
PWM1[6]:脈寬調製器1輸出6 |
||
O |
DTR1:UART1數據終止就緒端 |
||
O |
TRACEPKT0/LCDAC:跟蹤分組位0/LCD行同步脈衝(STN)水平同步脈衝(TFT) |
||
P2[6] |
138 |
I/O |
P2[6]:GPIO口 |
I |
PCAP1[0]:脈寬調製器1捕獲輸入通道0 |
||
I |
RI1:UART1響鈴指示輸入端 |
||
O |
TRACEPKT1/LCD[0]/LCD[4]:跟蹤分組位1/LCD數據 |
||
P2[7] |
136 |
I/O |
P2[7]:GPIO口 |
I |
RD2:CAN2接收輸入 |
||
O |
RTS1:UART1請求發送輸出端 |
||
O |
TRACEPKT2/LCD[1]/LCD[5]:跟蹤分組位1/LCD數據 |
||
P2[8] |
134 |
I/O |
P2[8]:GPIO口 |
O |
TD2:CAN2發送輸出 |
||
O |
TXD2:UART2接收輸入端 |
||
O |
TRACEPKT3/LCD[2]/LCD[6]:跟蹤分組位3/LCD數據 |
||
P2[9] |
132 |
I/O |
P2[9]:GPIO口 |
O |
USB_CONNECT1:USB1軟鏈接控制 |
||
I |
RXD2:UART2接收輸入 |
||
I |
EXTINT0/LCD[3]/LCD[7]:外部觸發中斷輸入/LCD數據 |
||
P2[10] |
110 |
I/O |
P2[10]:GPIO口 |
I |
EINT0:外部中斷0輸入 |
||
P2[11] |
108 |
I/O |
P2[11]:GPIO口 |
I/O |
EINT1:外部中斷1輸入/LCDCLKIN:LCD時鐘 |
||
I/O |
MCIDAT1:SD/MMC接口數據線1 |
||
I/O |
I2STX_CLK:I2S傳輸時鐘。 |
||
P2[12] |
106 |
I/O |
P2[12]:GPIO口 |
I/O |
EINT2:外部中斷2輸入/輸出:LCD[4]/LCD[3]/LCD[8]/LCD[18] |
||
I/O |
MCIDAT2:SD/MMC接口數據線2 |
||
I/O |
I2STX_WS:I2S傳輸字選擇。 |
||
P2[13] |
102 |
I/O |
P2[13]:GPIO口 |
I/O |
EINT3:外部中斷3輸入/輸出:LCD[5]/LCD[9]/LCD[19] |
||
I/O |
MCIDAT3:SD/MMC接口數據線3 |
||
I/O |
I2STX_SDA:I2S傳輸數據。 |
||
P2[14] |
91 |
I/O |
P2[14]:GPIO口 |
O |
CS2:低電平有效片選信號2 |
||
I |
CAP2[0]:Tmer2捕獲輸入通道0 |
||
I/O |
SDA1:I2C1數據輸入/輸出 |
||
P2[15] |
99 |
I/O |
P2[15]:GPIO口 |
O |
CS3:低電平有效片選信號3 |
||
I |
CAP2[1]:Tmer2捕獲輸入通道1 |
||
I/O |
SCL1:I2C1時鐘輸入/輸出 |
||
P2[16] |
87 |
I/O |
P2[16]:GPIO口 |
O |
CAS:低電平有效SDRAM列地址選擇 |
||
P2[17] |
95 |
I/O |
P2[17]:GPIO口 |
O |
RAS:低電平有效SDRAM行地址選擇 |
||
P2[18] |
59 |
I/O |
P2[18]:GPIO口 |
O |
CLKOUT0:SDRAM時鐘0 |
||
P2[19] |
67 |
I/O |
P2[19]:GPIO口 |
O |
CLKOUT1:SDRAM時鐘1 |
||
P2[20] |
73 |
I/O |
P2[20]:GPIO口 |
O |
DYCS0:SDRAM片選信號0 |
||
P2[21] |
81 |
I/O |
P2[21]:GPIO口 |
O |
DYCS1:SDRAM片選信號1 |
||
P2[22] |
85 |
I/O |
P2[22]:GPIO口 |
O |
DYCS2:SDRAM片選信號2 |
||
I |
CAP3[0]:Timer3捕獲輸入通道0 |
||
I/O |
SCK0:SSP0串行時鐘 |
||
P2[23] |
64 |
I/O |
P2[23]:GPIO口 |
O |
DYCS3:SDRAM片選信號3 |
||
I |
CAP3[1]:Timer3捕獲輸入通道1 |
||
I/O |
SSEL0:SSP0從機選擇 |
||
P2[24] |
53 |
I/O |
P2[24]:GPIO口 |
O |
CKEOUT0:SDRAM時鐘使能信號0 |
||
P2[25] |
54 |
I/O |
P2[25]:GPIO口 |
O |
CKEOUT1:SDRAM時鐘使能信號1 |
||
P2[26] |
57 |
I/O |
P2[26]:GPIO口 |
O |
CKEOUT2:SDRAM時鐘使能信號2 |
||
O |
MAT3[0]:Tmer3匹配輸出通道0 |
||
I/O |
MISO0:SSP0主機輸入從機輸出 |
||
P2[27] |
47 |
I/O |
P2[27]:GPIO口 |
O |
CKEOUT3:SDRAM時鐘使能信號3 |
||
O |
MAT3[1]:Tmer3匹配輸出通道1 |
||
I/O |
MOSI0:SSP0主機輸出從機輸入 |
||
P2[28] |
49 |
I/O |
P2[28]:GPIO口 |
O |
DQMOUT0:用於SDRAM和靜態設備的數據掩碼0 |
||
P2[29] |
43 |
I/O |
P2[29]:GPIO口 |
O |
DQMOUT1:用於SDRAM和靜態設備的數據掩碼1 |
||
P2[30] |
31 |
I/O |
P2[30]:GPIO口 |
O |
DQMOUT2:用於SDRAM和靜態設備的數據掩碼2 |
||
O |
MAT3[2]:Tmer3匹配輸出通道2 |
||
I/O |
SDA2:I2C2數據輸入/輸出 |
||
P2[31] |
39 |
I/O |
P2[31]:GPIO口 |
O |
DQMOUT3:用於SDRAM和靜態設備的數據掩碼3 |
||
O |
MAT3[3]:Tmer3匹配輸出通道3 |
||
I/O |
SCL2:I2C2時鐘輸入/輸出 |
4. P3口: P3口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P3口管腳描述如表4.4所示。
表4.4 LPC2400的P3口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P3[0] |
197 |
I/O |
P3[0]:GPIO口 |
I/O |
D0:外部存儲器數據線0 |
||
P3[1] |
201 |
I/O |
P3[1]:GPIO口 |
I/O |
D1:外部存儲器數據線1 |
||
P3[2] |
207 |
I/O |
P3[2]:GPIO口 |
I/O |
D2:外部存儲器數據線2 |
||
P3[3] |
3 |
I/O |
P3[3]:GPIO口 |
I/O |
D3:外部存儲器數據線3 |
||
P3[4] |
13 |
I/O |
P3[4]:GPIO口 |
I/O |
D4:外部存儲器數據線4 |
||
P3[5] |
17 |
I/O |
P3[5]:GPIO口 |
I/O |
D5:外部存儲器數據線5 |
||
P3[6] |
23 |
I/O |
P3[6]:GPIO口 |
I/O |
D6:外部存儲器數據線6 |
||
P3[7] |
27 |
I/O |
P3[7]:GPIO口 |
I/O |
D7:外部存儲器數據線7 |
||
P3[8] |
191 |
I/O |
P3[8]:GPIO口 |
I/O |
D8:外部存儲器數據線8 |
||
P3[9] |
199 |
I/O |
P3[9]:GPIO口 |
I/O |
D9:外部存儲器數據線9 |
||
P3[10] |
205 |
I/O |
P3[10]:GPIO口 |
I/O |
D10:外部存儲器數據線10 |
||
P3[11] |
208 |
I/O |
P3[11]:GPIO口 |
I/O |
D11:外部存儲器數據線11 |
||
P3[12] |
1 |
I/O |
P3[12]:GPIO口 |
I/O |
D12:外部存儲器數據線12 |
||
P3[13] |
7 |
I/O |
P3[13]:GPIO口 |
I/O |
D13:外部存儲器數據線13 |
||
P3[14] |
21 |
I/O |
P3[14]:GPIO口 |
I/O |
D14:外部存儲器數據線14 |
||
P3[15] |
28 |
I/O |
P3[15]:GPIO口 |
I/O |
D15:外部存儲器數據線15 |
||
P3[16] |
137 |
I/O |
P3[16]:GPIO口 |
I/O |
D16:外部存儲器數據線16 |
||
O |
PWM0[1]:脈寬調製器0輸出1 |
||
O |
TXD1:UART1發送輸出端 |
||
P3[17] |
143 |
I/O |
P3[17]:GPIO口 |
I/O |
D17:外部存儲器數據線17 |
||
O |
PWM0[2]:脈寬調製器0輸出2 |
||
I |
RXD1:UART1接收輸入端 |
||
P3[18] |
151 |
I/O |
P3[18]:GPIO口 |
I/O |
D18:外部存儲器數據線18 |
||
O |
PWM0[3]:脈寬調製器0輸出3 |
||
I |
CTS1:UART1清除發送輸入端 |
||
P3[19] |
161 |
I/O |
P3[19]:GPIO口 |
I/O |
D19:外部存儲器數據線19 |
||
O |
PWM0[4]:脈寬調製器0輸出4 |
||
I |
DCD1:UART1數據載波檢測輸入端 |
||
P3[20] |
167 |
I/O |
P3[20]:GPIO口 |
I/O |
D20:外部存儲器數據線20 |
||
O |
PWM0[5]:脈寬調製器0輸出5 |
||
I |
DSR1:UART1數據設置就緒端 |
||
P3[21] |
175 |
I/O |
P3[21]:GPIO口 |
I/O |
D21:外部存儲器數據線21 |
||
O |
PWM0[6]:脈寬調製器0輸出6 |
||
O |
DTR1:UART1數據終端準備就緒輸出端 |
||
P3[22] |
195 |
I/O |
P3[22]:GPIO口 |
I/O |
D22:外部存儲器數據線22 |
||
I |
PCAP0[0]:脈寬調製器0捕獲輸入通道0 |
||
I |
RI1:UART1響鈴指示輸入端 |
||
P3[23] |
65 |
I/O |
P3[23]:GPIO口 |
I/O |
D23:外部存儲器數據線23 |
||
I |
CAP0[0]:Timer0捕獲輸入通道0 |
||
I |
PCAP1[0]:脈寬調製器1捕獲輸入通道0 |
||
P3[24] |
58 |
I/O |
P3[24]:GPIO口 |
I/O |
D24:外部存儲器數據線24 |
||
I |
CAP0[1]:Timer0捕獲輸入通道1 |
||
O |
PWM1[1]:脈寬調製器1輸出1 |
||
P3[25] |
56 |
I/O |
P3[25]:GPIO口 |
I/O |
D25:外部存儲器數據線25 |
||
O |
MAT0[0]:Tmer0匹配輸出通道0 |
||
O |
PWM1[2]:脈寬調製器1輸出2 |
||
P3[26] |
55 |
I/O |
P3[26]:GPIO口 |
I/O |
D26:外部存儲器數據線26 |
||
O |
MAT0[1]:Tmer0匹配輸出通道1 |
||
O |
PWM1[3]:脈寬調製器1輸出3 |
||
P3[27] |
203 |
I/O |
P3[27]:GPIO口 |
I/O |
D27:外部存儲器數據線27 |
||
I |
CAP1[0]:Timer1捕獲輸入通道0 |
||
O |
PWM1[4]:脈寬調製器1輸出4 |
||
P3[28] |
5 |
I/O |
P3[28]:GPIO口 |
I/O |
D28:外部存儲器數據線28 |
||
I |
CAP1[1]:Timer1捕獲輸入通道1 |
||
O |
PWM1[5]:脈寬調製器1輸出5 |
||
P3[29] |
11 |
I/O |
P3[29]:GPIO口 |
I/O |
D29:外部存儲器數據線29 |
||
O |
MAT1[0]:Tmer1匹配輸出通道0 |
||
O |
PWM1[6]:脈寬調製器1輸出6 |
||
P3[30] |
19 |
I/O |
P3[30]:GPIO口 |
I/O |
D30:外部存儲器數據線30 |
||
O |
MAT1[1]:Tmer1匹配輸出通道1 |
||
O |
RTS1:UART1請求發送輸出端 |
||
P3[31] |
25 |
I/O |
P3[31]:GPIO口 |
I/O |
D31:外部存儲器數據線31 |
||
O |
MAT1[2]:Tmer1匹配輸出通道2 |
5. P4口: P4口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P4口管腳描述如表4.5所示。
表4.5 LPC2400的P4口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P4[0] |
75 |
I/O |
P4[0]:GPIO口 |
I/O |
A0:外部存儲器地址線0 |
||
P4[1] |
79 |
I/O |
P4[1]:GPIO口 |
I/O |
A1:外部存儲器地址線1 |
||
P4[2] |
83 |
I/O |
P4[2]:GPIO口 |
I/O |
A2:外部存儲器地址線2 |
||
P4[3] |
97 |
I/O |
P4[3]:GPIO口 |
I/O |
A3:外部存儲器地址線3 |
||
P4[4] |
103 |
I/O |
P4[4]:GPIO口 |
I/O |
A4:外部存儲器地址線4 |
||
P4[5] |
107 |
I/O |
P4[5]:GPIO口 |
I/O |
A5:外部存儲器地址線5 |
||
P4[6] |
113 |
I/O |
P4[6]:GPIO口 |
I/O |
A6:外部存儲器地址線6 |
||
P4[7] |
121 |
I/O |
P4[7]:GPIO口 |
I/O |
A7:外部存儲器地址線7 |
||
P4[8] |
1271 |
I/O |
P4[8]:GPIO口 |
I/O |
A8:外部存儲器地址線8 |
||
P4[9] |
131 |
I/O |
P4[9]:GPIO口 |
I/O |
A9:外部存儲器地址線9 |
||
P4[10] |
135 |
I/O |
P4[10]:GPIO口 |
I/O |
A10:外部存儲器地址線10 |
||
P4[11] |
145 |
I/O |
P4[11]:GPIO口 |
I/O |
A11:外部存儲器地址線11 |
||
P4[12] |
149 |
I/O |
P4[12]:GPIO口 |
I/O |
A12:外部存儲器地址線12 |
||
P4[13] |
155 |
I/O |
P4[13]:GPIO口 |
I/O |
A13:外部存儲器地址線13 |
||
P4[14] |
159 |
I/O |
P4[14]:GPIO口 |
I/O |
A14:外部存儲器地址線14 |
||
P4[15] |
173 |
I/O |
P4[15]:GPIO口 |
I/O |
A15:外部存儲器地址線15 |
||
P4[16] |
101 |
I/O |
P4[16]:GPIO口 |
I/O |
A16:外部存儲器地址線16 |
||
P4[17] |
104 |
I/O |
P4[17]:GPIO口 |
I/O |
A17:外部存儲器地址線17 |
||
P4[18] |
105 |
I/O |
P4[18]:GPIO口 |
I/O |
A18:外部存儲器地址線18 |
||
P4[19] |
111 |
I/O |
P4[19]:GPIO口 |
I/O |
A19:外部存儲器地址線19 |
||
P4[20] |
109 |
I/O |
P4[20]:GPIO口 |
I/O |
A20:外部存儲器地址線20 |
||
I/O |
SDA2:I2C2數據輸入/輸出 |
||
I/O |
SCK1:SSP1串行時鐘 |
||
P4[21] |
115 |
I/O |
P4[21]:GPIO口 |
I/O |
A21:外部存儲器地址線21 |
||
I/O |
SCL2:I2C2時鐘輸入/輸出 |
||
I/O |
SSEL1:SSP1從機選擇 |
||
P4[22] |
123 |
I/O |
P4[22]:GPIO口 |
I/O |
A22:外部存儲器地址線22 |
||
O |
TXD2:UART2發送輸出端 |
||
I/O |
MISO1:SSP1主機輸入從機輸出 |
||
P4[23] |
129 |
I/O |
P4[23]:GPIO口 |
I/O |
A23:外部存儲器地址線23 |
||
I |
RXD2:UART2接收輸入端 |
||
I/O |
MOSI1:SSP1主機輸出從機輸入 |
||
P4[24] |
183 |
I/O |
P4[24]:GPIO口 |
O |
OE:低電平有效輸出使能信號 |
||
P4[25] |
179 |
I/O |
P4[25]:GPIO口 |
O |
WE:低電平有效寫使能信號 |
||
P4[26] |
119 |
I/O |
P4[26]:GPIO口 |
O |
BLS0:低電平有效字節定位選擇信號0 |
||
P4[27] |
139 |
I/O |
P4[27]:GPIO口 |
O |
BLS1:低電平有效字節定位選擇信號1 |
||
P4[28] |
170 |
I/O |
P4[28]:GPIO口 |
O |
BLS2:低電平有效字節定位選擇信號2 |
||
O |
MAT2[0]/LCD[6]/LCD[10]/LCD[2]:Timer2匹配輸出通道0/LCD數據 |
||
O |
TXD3:UART3發送輸出端 |
||
P4[29] |
176 |
I/O |
P4[29]:GPIO口 |
O |
BLS3:低電平有效字節定位選擇信號3 |
||
O |
MAT2[1]/LCD[7]/LCD[11]/LCD[3]:Timer2匹配輸出通道1/LCD數據 |
||
I |
RXD3:UART3接收輸入端 |
||
P4[30] |
187 |
I/O |
P4[30]:GPIO口 |
O |
CS0:低電平有效片選信號0 |
||
P4[31] |
193 |
I/O |
P4[31]:GPIO口 |
O |
CS1:低電平有效片選信號1 |
6. 電源、復位、晶振及其它管腳的描述如表4.6所示。
表4.6 LPC2400的其它管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
ALARM |
37 |
O |
RTC實時時鐘控制輸出。這是一個1.8V引腳,當RTC產生報警信號時此引腳變爲高電平。 |
USB_D-2 |
52 |
I/O |
USB端口2雙向D-線 |
DBGEN |
9 |
I |
JTAG接口控制信號,也用於邊界掃描 |
TDO |
2 |
O |
JTAG接口測試數據輸出 |
TDI |
4 |
I |
JTAG接口測試數據輸入 |
TMS |
6 |
I |
JTAG接口測試模式選擇 |
TRST |
8 |
I |
JTAG接口測試復位,低電平有效 |
TCK |
10 |
I |
JTAG接口測試時鐘 |
RTCK |
206 |
I/O |
JTAG接口控制信號,當此引腳低電平時使能ETM引腳(P2[9:0]),用於復位後操做跟蹤端口 |
RSTOUT |
29 |
O |
這是個1.8V引腳,當此引腳低電平時表示LPC2478處於復位狀態 |
RESET |
35 |
I |
外部復位輸入,低電平有效。該引腳具備遲滯做用的TTL電平,能承受5V電壓,當此引腳低電平時器件復位,I/O口和外圍功能進入默認狀態,處理器從地址0開始執行程序 |
XTAL1 |
44 |
I |
振盪器電路和內部時鐘發生電路輸入 |
XTAL2 |
46 |
O |
振盪放大器輸出 |
RTCX1 |
34 |
I |
RTC振盪器電路輸入 |
RTCX2 |
36 |
O |
RTC振盪器電路輸出 |
VSSIO |
33,63,77,93,114,133,148,169,189,200 |
I |
地:數字IO腳的0V電壓參考點 |
VSSCORE |
32,84,172 |
I |
地:處理器內核的0V電壓參考點 |
VSSA |
22 |
I |
模擬地:0V電壓參考點,與VSS電壓相同,爲了下降噪聲和出錯概率,二者應當隔離 |
VDD(3V3) |
15,60,71,89,112,125,146,165,181,198 |
I |
3.3V供應電壓:I/O口電源供應電壓 |
NC |
30,117,141 |
I |
未鏈接引腳 |
VDD(DCDC)(3V3) |
26,86,174 |
I |
3.3V直流到直流轉換供應電壓:爲片內DC-to-DC轉換器提供電源 |
VDDA |
20 |
I |
模擬3.3V供應電壓:爲DAC和ADC供電,與VDD(3V3)電壓相同,爲了下降噪聲和出錯概率,二者應當隔離 |
VREF |
24 |
I |
ADC參考電壓:與VDD(3V3)電壓相同,爲了下降噪聲和出錯概率,二者應當隔離,爲ADC和DAC提供參考電壓 |
VBAT |
38 |
I |
RTC電源供應:3.3V,爲RTC提供電源 |
注:1. 本引腳定義表以LPC2478爲準,LPC2470與此相同,LPC2468沒有引腳定義的LCD部分。
2. 類型表示引腳信號方向:I/O爲輸入/輸出,I爲輸入,O爲輸出。
從表4.1~表4.6能夠看到,LPC2400系列芯片的絕大部分引腳是複用的,每根引腳都有可能用於不一樣的外設功能。引腳具體用於什麼外設功能是由引腳鏈接模塊進行配置來實現的。當引腳選擇了一個功能時,則其它功能無效。
在使用外設時,應當在激活外設以及使能任何相關的中斷以前,將外設鏈接到相應的引腳上。不然,即便使用引腳鏈接模塊激活外設,此激活也是無效的。
引腳鏈接模塊共有21個寄存器,包括11個引腳功能選擇寄存器和10個引腳模式寄存器。
1. 引腳功能選擇寄存器(PINSEL0~PINSEL10)
引腳功能選擇寄存器用於控制每一個引腳的功能,每一個寄存器32位,每2個bit用於控制1個引腳功能選擇。以PINSEL0寄存器爲例,寄存器的[1:0]位用於控制P0[0]引腳,[3:2]位用於控制P0[1]引腳,[31:30]位用於控制P0[15]引腳。而PINSEL1寄存器的[1:0]位用於控制P0[16]引腳,[3:2]位用於控制P0[17]引腳,[31:30]位用於控制P0[31]引腳。其他依次類推。
PINSEL0~PINSEL9寄存器,每兩個寄存器用於一個端口組:PINSEL0寄存器用於P0口的[15:0]引腳,PINSEL1寄存器用於P0口的[31:30]引腳;PINSEL2寄存器用於P1口的[15:0]引腳,PINSEL3寄存器用於P1口的[31:30]引腳;PINSEL4寄存器用於P2口的[15:0]引腳,PINSEL5寄存器用於P2口的[31:30]引腳;PINSEL6寄存器用於P3口的[15:0]引腳,PINSEL7寄存器用於P3口的[31:30]引腳;PINSEL8寄存器用於P4口的[15:0]引腳,PINSEL9寄存器用於P4口的[31:30]引腳。
每一對比特設置引腳功能的定義如表4.7所示。
表4.7 引腳功能選擇寄存器位
PINSEL0~PINSEL9值 |
功能 |
復位值 |
00 |
主功能(缺省),通常爲GPIO口 |
00 |
01 |
第一備用功能 |
|
10 |
第二備用功能 |
|
11 |
第三備用功能 |
每一個引腳默認爲GPIO口,經過設置PINSEL的值來定義其引腳功能。以P0[0]腳爲例,當PINSEL0寄存器的[1:0]位爲00時,引腳功能爲GPIO口;爲01時,引腳功能爲CAN1接收器輸入;爲10時,引腳功能爲UART3發送輸出端;爲11時,引腳功能爲I2C1數據輸入/輸出。
每一個引腳的具體定義方法參見表4.1~表4.6。表格中的引腳功能按PINSEL值排列。某些引腳只有兩種功能,此時只使用PINSEL值00和01,值10和11保留。
PINSEL10寄存器用於控制ETM接口引腳。該寄存器只使用了位3,其他位均保留。當第3位爲0時,關閉ETM接口功能;爲1時啓用ETM跟蹤接口功能,此時不管PINSEL4怎麼定義,P2[0]~P2[8]腳均用於ETM跟蹤功能。
引腳功能被選擇爲GPIO時,引腳的方向控制由GPIO方向寄存器IODIR控制。對於其它功能,引腳的方向是由引腳功能控制的。
2. 引腳模式寄存器(PINMODE0~PINMODE9)
引腳模式寄存器PINMODE爲全部的GPIO端口控制片內上拉/下拉電阻特性。當使用片內上拉或下接電阻時,若引腳信號不肯定,使用上拉時爲高電平;而下拉時拉爲低電平。
與PNSEL寄存器同樣,PINMODE寄存器每2個bit控制1個引腳。每兩個寄存器控制一個端口組。
PINMOD寄存器取值如表4.8所示。
表4.8 引腳模式寄存器位
PINMODE0~PINMODE9值 |
功能 |
復位值 |
00 |
使能引腳片內上拉電阻 |
00 |
01 |
保留 |
|
10 |
既不使用上拉也不使用下拉 |
|
11 |
使能引腳片內下拉電阻 |
引腳鏈接模塊的寄存器總表如表4.9所示。
表4.9 引腳控制模塊寄存器列表
寄存器名 |
描述 |
訪問 |
復位值 |
地址 |
PINSEL0 |
引腳功能選擇寄存器0 |
讀/寫 |
0x0000 0000 |
0xE002 C000 |
PINSEL1 |
引腳功能選擇寄存器1 |
讀/寫 |
0x0000 0000 |
0xE002 C004 |
PINSEL2 |
引腳功能選擇寄存器2 |
讀/寫 |
0x0000 0000 |
0xE002 C008 |
PINSEL3 |
引腳功能選擇寄存器3 |
讀/寫 |
0x0000 0000 |
0xE002 C00C |
PINSEL4 |
引腳功能選擇寄存器4 |
讀/寫 |
0x0000 0000 |
0xE002 C010 |
PINSEL5 |
引腳功能選擇寄存器5 |
讀/寫 |
0x0000 0000 |
0xE002 C014 |
PINSEL6 |
引腳功能選擇寄存器6 |
讀/寫 |
0x0000 0000 |
0xE002 C018 |
PINSEL7 |
引腳功能選擇寄存器7 |
讀/寫 |
0x0000 0000 |
0xE002 C01C |
PINSEL8 |
引腳功能選擇寄存器8 |
讀/寫 |
0x0000 0000 |
0xE002 C020 |
PINSEL9 |
引腳功能選擇寄存器9 |
讀/寫 |
0x0000 0000 |
0xE002 C024 |
PINSEL10 |
引腳功能選擇寄存器10 |
讀/寫 |
0x0000 0000 |
0xE002 C028 |
PINMODE0 |
引腳模式寄存器0 |
讀/寫 |
0x0000 0000 |
0xE002 C040 |
PINMODE1 |
引腳模式寄存器1 |
讀/寫 |
0x0000 0000 |
0xE002 C044 |
PINMODE2 |
引腳模式寄存器2 |
讀/寫 |
0x0000 0000 |
0xE002 C048 |
PINMODE3 |
引腳模式寄存器3 |
讀/寫 |
0x0000 0000 |
0xE002 C04C |
PINMODE4 |
引腳模式寄存器4 |
讀/寫 |
0x0000 0000 |
0xE002 C050 |
PINMODE5 |
引腳模式寄存器5 |
讀/寫 |
0x0000 0000 |
0xE002 C054 |
PINMODE6 |
引腳模式寄存器6 |
讀/寫 |
0x0000 0000 |
0xE002 C058 |
PINMODE7 |
引腳模式寄存器7 |
讀/寫 |
0x0000 0000 |
0xE002 C05C |
PINMODE8 |
引腳模式寄存器8 |
讀/寫 |
0x0000 0000 |
0xE002 C060 |
PINMODE9 |
引腳模式寄存器9 |
讀/寫 |
0x0000 0000 |
0xE002 C064 |
LPC2400系列芯片外設功能在使用前必須先設置其引腳功能。引腳功能是經過對引腳鏈接模塊編程來實現的。
例4.1:使用串口UART0
串口UART0只使用TXD0和RXD0兩根引腳來進行數據的串行發送和接收,使用時需將對應的兩根引腳P0[2]和P0[3]設置成TXD0和RXD0功能。查表4.1可知,兩根引腳的對應PINSEL值均爲01,所以寫入PINSEL0寄存器的值爲0x00000050。
相應程序行爲:
PINSEL0 = 0x00000050;
或
PINSEL0 = 0x05<<4;
注意,因爲PINSEL是可讀寫的寄存器,上述寫法會使其它引腳的功能回到初始化默認配置。爲了避免影響其它引腳的功能配置,實用中更好的辦法是:先讀取寄存器值,而後進行邏輯與和邏輯或操做,再回寫到寄存器。
PINSEL0 = (PINSEL0 &0xFFFFFF0F) | (0x05<<4);
其他的引腳外設功能都可以採用相似方法進行操做。
例4.2:啓動代碼中的相關部分
啓動代碼負責對芯片復位後的硬件功能進行初始化。芯片復位時,各PINSEL寄存器會自動設置爲默認值,因此復位後芯片引腳的功能是肯定的。
若是啓動之後,硬件系統各外設功能使用狀況比較固定,能夠將對應的引腳功能設置寫入啓動代碼以加快啓動速度。不然,能夠在啓動時將全部引腳都配置成GPIO端口,具體使用某部分外設時再對相關引腳進行初始化。
……
PINSEL0 = 0x00000000;
PINSEL1 = 0x00000000;
PINSEL2 = 0x00000000;
PINSEL3 = 0x00000000;
PINSEL4 = 0x00000000;
PINSEL5 = 0x00000000;
PINSEL6 = 0x00000000;
PINSEL7 = 0x00000000;
PINSEL8 = 0x00000000;
PINSEL9 = 0x00000000;
PINSEL10 = 0x00000000;
……
LPC2400系列芯片集成了512KB的片內Flash存儲器和64KB的靜態SRAM(LPC2470沒有片內Flash),其中Flash存儲器能夠用作代碼和數據的固態存儲。對Flash存儲器的編程能夠經過幾種方法來實現:經過串口UART0進行的在系統編程(ISP),經過調用嵌入片內的固化代碼進行的在應用編程(IAP)以及經過內置的JTAG接口編程。
SRAM支持8位、16位和32位訪問。須要注意的是,SRAM控制器包含一個回寫緩衝區,它用於防止CPU在連續的寫操做時中止運行。回寫緩衝區老是保存着軟件發送到SRAM的最後1字節。數據只有在軟件執行另一次寫操做時被寫入SRAM。若是發生芯片復位,實際的SRAM內容將不會反映最近一次的寫請求。任何在復位後檢查SRAM內容的程序都必須注意這一點。
LPC2400系列芯片具有外部存儲器接口,經過外部存儲器控制器(EMC)能夠擴展兩組共8個Bank的存儲器組(Static memory bank0 ~ bank3,Dynamic memory bank0 ~ bank3)。對於外擴的RAM存儲器,使用ARM的LDR/STR指令便可進行數據的讀寫操做;而對於外擴的Flash(NOR)型,能夠使用LDR指令讀取數據,可是不能使用STR指令直接寫數據,而是根據Flash芯片寫操做時序進行控制,實現Flash的擦除編程。若是須要將程序代碼燒寫到擴展的Flash,則須要運行一個裝載程序(Loader程序,通常由用戶自行編寫),而後由Loader程序對Flash存儲器進行擦除和燒寫。
ARM處理器共有4GB的尋址空間,LPC2400系列處理器將這個空間劃分紅了幾個不一樣的存儲器組。圖4.3所示爲復位後從用戶角度所看到的系統存儲器地址空間映射。
圖4.3 LPC2400系統存儲器映射
表4.10 LPC2400存儲器使用和細節
地址範圍 |
通用用途 |
地址範圍細節 |
功能描述 |
0x0000 0000 - 0x3FFF FFFF |
片內非易失存儲器和快速I/O |
0x0000 0000 – 0x0007 FFFF |
Flash 存儲器(512KB) |
0x3FFF C000 – 0x3FFF FFFF |
快速GPIO寄存器 |
||
0x4000 0000 - 0x7FFF FFFF |
片內存儲器 |
0x4000 0000 – 0x4000 FFFF |
RAM(64KB) |
0x7FE0 0000 – 0x7FE0 3FFF |
以太網RAM(16KB) |
||
0x7FD0 0000 – 0x7FD0 3FFF |
USB RAM(16KB) |
||
0x8000 0000 - 0xDFFF FFFF
|
片外存儲器 |
四個靜態存儲器bank,每一個16MB |
|
0x8000 0000 – 0x80FF FFFF |
靜態存儲器bank0 |
||
0x8100 0000 – 0x81FF FFFF |
靜態存儲器bank1 |
||
0x8200 0000 – 0x82FF FFFF |
靜態存儲器bank2 |
||
0x8300 0000 – 0x83FF FFFF |
靜態存儲器bank3 |
||
四個動態存儲器bank,每一個256MB |
|||
0xA000 0000 – 0xAFFF FFFF |
動態存儲器bank0 |
||
0xB000 0000 – 0x3FFF FFFF |
動態存儲器bank1 |
||
0xC000 0000 – 0xCFFF FFFF |
動態存儲器bank2 |
||
0xD000 0000 – 0xDFFF FFFF |
動態存儲器bank3 |
||
0xE000 0000 - 0xEFFF FFFF |
APB 外設 |
36個外設模塊,每一個16KB |
|
0xF000 0000 - 0xFFFF FFFF |
AHB 外設 |
|
1. 外設存儲器映射
LPC2400系列處理器的外設根據內部總線分爲AHB和APB外設兩類。AHB外設和APB外設在存儲空間裏都佔2MB的區域,可各自分配最多128個外設。每一個外設空間的規格都爲16KB。全部外設寄存器無論規格大小,都按照字地址進行分配(32位邊界),且無論字仍是半字寄存器都是一次性訪問。例如,不可能對一個字寄存器的最高字節執行單獨的讀或寫操做。
圖4.4表示了AHB和APB外設佔用存儲空間示意圖。
圖4.4 外設存儲器映射(AHB外設和APB外設)
圖4.5所示爲AHB外設佔用存儲空間示意圖。其中0-4號外設分別分配給以太網控制器、GPDMA控制器、EMC控制器、USB控制器和LCD控制器,其它外設編號未使用。
圖4.5 AHB外設存儲器映射
表4.11所示爲APB外設佔用的存儲空間示意圖。
表4.11 APB外設存儲器映射
APB 外設 |
基地址 |
外設名 |
0 |
0xE000 0000 |
看門狗 |
1 |
0xE000 4000 |
定時器0 |
2 |
0xE000 8000 |
定時器1 |
3 |
0xE000 C000 |
UART0 |
4 |
0xE001 0000 |
UART1 |
5 |
0xE001 4000 |
PWM0 |
6 |
0xE001 8000 |
PWM1 |
7 |
0xE001 C000 |
I2C0 |
8 |
0xE002 0000 |
SPI |
9 |
0xE002 4000 |
實時時鐘RTC |
10 |
0xE002 8000 |
GPIO |
11 |
0xE002 C000 |
引腳鏈接模塊 |
12 |
0xE003 0000 |
SSP1 |
13 |
0xE003 4000 |
ADC |
14 |
0xE003 8000 |
CAN接收濾波器RAM |
15 |
0xE003 C000 |
CAN接收濾波器寄存器 |
16 |
0xE004 0000 |
CAN通用寄存器 |
17 |
0xE004 4000 |
CAN控制器1 |
18 |
0xE004 8000 |
CAN控制器2 |
19 到 22 |
0xE004 C000 - 0xE005 8000 |
未使用 |
23 |
0xE005 C000 |
I2C1 |
24 |
0xE006 0000 |
未使用 |
25 |
0xE006 4000 |
未使用 |
26 |
0xE006 8000 |
SSP0 |
27 |
0xE006 C000 |
DAC |
28 |
0xE007 0000 |
定時器2 |
29 |
0xE007 4000 |
定時器3 |
30 |
0xE007 8000 |
UART2 |
31 |
0xE007 C000 |
UART3 |
32 |
0xE008 0000 |
I2C3 |
33 |
0xE008 4000 |
電池RAM |
34 |
0xE008 8000 |
I2S |
35 |
0xE008 C000 |
SD/MMC卡接口 |
36 到126 |
0xE009 0000 - 0xE01F BFFF |
未使用 |
127 |
0xE01F C000 |
系統控制模塊 |
在對LPC2400系列芯片編程時,要注意不要對一個保留地址或未使用區域的地址進行尋址,不然LPC2400將產生一個數據停止異常。另外,對AHB或APB外設地址執行任何指令取指都會致使產生預取指停止異常。
2. 存儲器重映射和boot ROM
存儲器映射的一個基本概念是:每一個存儲器組在存儲器映射中都有一個「物理上的」位置。它是一個地址範圍,該範圍內可寫入程序代碼,每個存儲器空間的容量都永久固定在同一個位置,這樣就不須要將代碼設計成在不一樣地址範圍內運行。
由於ARM7處理器上的中斷向量所處具體位置(地址0x0000 0000~0x0000 001C,見表4.12)的要求,Boot ROM和SRAM空間的一小部分空間須要從新映射,來實如今不一樣操做模式下對中斷的不一樣使用。
表4.12 ARM 異常向量位置
地址 |
異常 |
0x0000 0000 |
復位 |
0x0000 0004 |
未定義指令 |
0x0000 0008 |
軟件中斷 |
0x0000 000C |
預取指停止(指令讀取存儲器出錯) |
0x0000 0010 |
數據停止(數據訪問存儲器出錯) |
0x0000 0014 |
保留 |
0x0000 0018 |
IRQ |
0x0000 001C |
FIQ |
爲了與未來器件兼容,整個Boot ROM都被映射到片內存儲器空間的頂端。在這種方式下,使用較大或較小的Flash模塊都不須要改變Boot ROM(須要改變Boot裝載程序自身的代碼)的位置或改變Boot ROM中斷向量的映射。除了中斷向量以外的存儲器空間都保持固定的位置。
存儲器從新映射的部分容許在不一樣模式下處理中斷。LPC2400共支持3種存儲器映射模式,見表4.13。當處理器工做在用戶Flash模式下時,不須要進行中斷向量的從新映射,而在其它模式下則須要從新映射。它包括中斷向量區(32 字節)和額外的32 字節,一共是64 字節。從新映射的代碼位置與地址0x0000 0000~0x0000 003F 重疊,包含在SRAM、Flash 和Boot Block 中的向量必須包含跳轉到實際中斷處理程序的分支或者其它執行跳轉到中斷處理程序的轉移指令。一個位於Flash 存儲器中的典型用戶程序能夠將整個FIQ 處理程序放置在地址0x0000 001C 而不須要考慮存儲器的邊界。
表4.13 LPC2400存儲器映射模式
模式 |
激活 |
用途 |
Boot裝載程序模式 |
由任何復位硬件激活 |
在任何復位後都會執行Boot 裝載程序。Boot ROM中斷向量映射到存儲器的底部以容許處理異常並在Boot 裝載過程當中使用中斷。 |
用戶Flash 模式 |
由Boot 代碼軟件激活 |
當在存儲器中識別了一個有效的用戶程序標識而且Boot 裝載操做未被執行時,由Boot 裝載程序激活。中斷向量不做從新映射,它位於Flash 存儲器的底部。 |
用戶RAM 模式 |
由用戶程序軟件激活 |
由用戶程序激活。中斷向量從新映射到靜態RAM 的底部。 |
選擇這種配置有三個緣由:
1) 使Flash 存儲器中的FIQ處理程序沒必要考慮由於從新映射所致使的存儲器邊界問題;
2) 用來處理代碼空間中段邊界仲裁的SRAM 和Boot ROM向量的使用大大減小;
3) 爲超過單字轉移指令範圍的跳轉提供空間來保存常量。
從新映射的存儲器組,包括Boot ROM和中斷向量,除了從新映射的地址外,仍然繼續出如今它們最初的位置。存儲器重映射之後的存儲器空間見圖4.6所示。
圖4.6已從新映射和可從新映射區域的低存儲器空間
3. 存儲器映射控制寄存器MEMMAP(Memory Mapping Control Register)
存儲器映射控制寄存器用於改變從地址0x00000000開始的中斷向量的映射。這容許運行在不一樣存儲器空間中的代碼對中斷進行控制。MEMMAP是一個可讀寫寄存器,地址爲0xE01FC040,功能爲選擇從Flash Boot Block、用戶Flash 或RAM中讀取ARM 中斷向量。
表4.14 存儲器映射控制寄存器MEMMAP
位 |
符號 |
功能描述 |
復位值 |
1:0 |
MAP |
00:Boot 裝載程序模式。中斷向量從Boot Block 從新映射 01:用戶Flash 模式。中斷向量不從新映射,它位於Flash 中 10:用戶RAM 模式。中斷向量從靜態RAM 從新映射 11:保留,不使用該選項 警告:不正確的設定會致使器件的錯誤操做 |
00 |
7:2 |
保留 |
|
NA |
LPC2400的MAP位的硬件復位值爲00。Boot裝載程序會將用戶看到的復位值更改,該程序老是在復位後當即運行。
存儲器映射控制寄存器MEMMAP只從處理ARM異常(中斷)必需的3 個數據源(FLASH中斷向量、SRAM中斷向量和Boot ROM中斷向量,每一個64 字節)中選擇一個使用。
每當產生一個軟件中斷請求,ARM內核就從0x0000 0008 處取出32 位數據(見表4.12,「ARM異常向量位置」)。這就意味着當MEMMAP[1:0]=10(用戶RAM模式)時,從0x0000 0008的讀數/取指是對0x4000 0008單元進行操做。當MEMMAP[1:0]=00(Boot裝載程序模式)時,從0x0000 0008的讀數/取指是對0x7FFF E008 單元的數據進行操做(Boot ROM從片內Flash存儲器從新映射)。
當LPC2400 在運行Flash存儲器內的代碼時,器件內部的存儲器加速模塊(MAM,Memory Accelerator Module)最大限度地提升了ARM處理器的性能,而此只須要使用一個簡單的Flash組就可實現了。
1.操做
存儲器加速模塊(MAM)能夠將須要的下一個ARM 指令鎖存,以防止CPU 取指暫停。與之前的其它器件使用2個Flash組相比,LPC2400只使用一組Flash 存儲器。這個Flash組包含3 個128位的緩衝區:預取指緩衝區、分支跟蹤緩衝區和數據緩衝區。
當預取指緩衝區和分支跟蹤緩衝區不能知足一次指令取指的須要,而且預取指尚未啓動時,ARM在啓動128位行的取指時暫停。若是預取指已經啓動但還未完成,則ARM暫停的時間會更短一些。預取指在Flash結束前面的訪問後當即啓動,除非被數據訪問停止。
預取指行被Flash 模塊鎖存,但MAM 不能在預取指緩衝區中捕獲該行,直到ARM 內核給出預取指開始的地址。若是內核給出的地址與預取指地址不一樣,則預取指行丟棄。
每一個預取指緩衝區和分支跟蹤緩衝區包含4個32位ARM指令或8個16位Thumb指令。在連續執行代碼時,一般預取指緩衝區包含當前指令和含有該指令的整個Flash 行。
分支和其它程序流的變化致使前面所講述的連續指令取指出現中斷。分支跟蹤緩衝區捕獲發生非連續中斷的行。若是相同的分支再次出現,則從分支跟蹤緩衝區內取出下條指令。當分支超出了預取指和分支跟蹤緩衝區內容時,須要停止幾個時鐘來裝載分支跟蹤緩衝區。這樣,不會再出現指令取指延時,直到一個新的和不一樣的分支出現。
2.MAM 結構
存儲器加速器分紅如下幾個功能模塊:1個Flash地址鎖存和1個增量器功能用於預取指地址、1個128位的預取指緩衝區及其相關的地址鎖存和比較器、1個128位的分支跟蹤緩衝區及其相關的地址鎖存和比較器。
圖4.7 存儲器加速器模塊框圖
3.MAM 的操做模式
MAM 定義了3種操做模式,用戶能夠在性能和可預測性之間進行選擇:
1)MAM關閉。全部存儲器請求都會致使Flash的讀操做,無指令預取指。
2)MAM部分使能。若是數據可用,則從保持鎖存區執行連續的指令訪問。指令預取指使能。非連續的指令訪問啓動Flash讀操做。這意味着全部的轉移指令都會致使對存儲器的取指。因爲緩衝的數據訪問時序很難預測而且很是依賴於所處的情況,所以全部數據操做都會致使Flash讀操做。
3)MAM 徹底使能。任何存儲器請求(代碼或數據),若是其值已經包含在其中一個保持鎖存當中,那麼從緩衝區執行該代碼或數據的訪問。指令預取指使能。Flash讀操做用於指令的預取指和當前緩衝區所沒有的代碼或數據的訪問。
在復位後,MAM 默認爲禁止狀態,軟件能夠隨時將存儲器訪問加速打開或關閉。這樣就可以使大多數應用程序以最高速度運行,而某些要求更精肯定時的功能能夠較慢但更可預測的速度運行。
在啓用MAM之後,Flash編程功能不受MAM的控制,而是做爲一個獨立的功能進行處理。Boot ROM扇區包含可做爲應用程序的一部分調用的Flash 編程算法(即IAP 代碼)和一個可對Flash 存儲器進行串行編程的裝載程序(即ISP 代碼)。
4.寄存器描述
1)MAM控制寄存器-MAM Control Register(MAMCR - 0xE01FC000)。決定MAM的操做模式。兩個配置位選擇MAM的3種操做模式。在復位後,MAM功能被禁止。改變MAM操做模式會致使MAM全部的保持鎖存內容無效,所以須要執行新的Flash讀操做。
表4.15 存儲器加速器模塊控制寄存器(MAMCR)
MAMCR |
功能 |
描述 |
復位值 |
1:0 |
MAM 模式控制 |
00-MAM 功能被禁止 01-MAM 功能部分使能 10-MAM 功能徹底使能 11-保留 |
0 |
7:2 |
保留 |
保留 |
NA |
2)MAM定時寄存器-MAM Timing Register(MAMTIM - 0xE01FC004)。決定Flash存儲器取指所使用的時鐘個數(1到7個處理器時鐘),使用多少個cclk週期訪問Flash存儲器。這樣可調整MAM時序使其匹配處理器操做頻率。Flash訪問時間能夠從1到7個時鐘,單個時鐘的Flash訪問實際上關閉了MAM,這種狀況下能夠選擇MAM模式對功耗進行優化。
表4.16 存儲器加速定時寄存器(MAMTIM)
MAMTIM |
功能 |
描述 |
復位值 |
2:0 |
MAM取指週期 |
000=0,保留 001=1,MAM 取指週期爲1 個處理器時鐘(cclk) 010=2,MAM 取指週期爲2 個處理器時鐘(cclk) 011=3,MAM 取指週期爲3 個處理器時鐘(cclk) 100=4,MAM 取指週期爲4 個處理器時鐘(cclk) 101=5,MAM 取指週期爲5 個處理器時鐘(cclk) 110=6,MAM 取指週期爲6 個處理器時鐘(cclk) 111=7,MAM 取指週期爲7 個處理器時鐘(cclk) 警告:不正確的設定會致使器件的錯誤操做! |
0x07 |
7:3 |
保留 |
保留 |
NA |
5.MAM 使用注意事項
1)MAM 定時值問題
當改變MAM定時值時,必須先經過向MAMCR寫入0來關閉MAM,而後將新值寫入MAMTIM,最後,將須要的操做模式的對應值寫入MAMCR,再次打開MAM。
對於低於20MHz的系統時鐘,MAMTIM設定爲1;對於20MHz到40MHz之間的系統時鐘,建議將MAMTIM設定爲2;而在高於40MHz的系統時鐘下,建議使用3。
2)Flash 編程問題
在編程和擦除操做過程當中不容許訪問Flash存儲器。若是在Flash模塊忙時存儲器請求訪問Flash地址,MAM就必須強制CPU等待(這經過聲明ARM7TDMI-S局部總線信號CLKEN來實現)。在某些狀況下,代碼執行的延遲會致使看門狗超時。用戶必須注意到這種可能性,並採起措施來確保不會在編程或擦除Flash 存儲器時出現非預期的看門狗復位,從而致使系統故障。
6.MAM使用舉例
MAM功能在LPC2400的啓動代碼中實現,能夠根據Fcclk的大小來自動設置MAM, (在target.c文件中)。首先要將MAM功能禁止,而後根據Fcclk的大小來設置MAM定時寄存器(經過條件編譯實現,Fcclk的定義在target.h文件中),最後再使能MAM。
代碼清單4.1
void TargetResetInit(void)
{ …
MAMCR = 0; // 禁止MAM 功能
#if Fcclk < 20000000
MAMTIM = 1; // 系統時鐘低於20M,建議設置爲1
#else
#if Fcclk < 40000000
MAMTIM = 2; // 系統時鐘再20M~40M 之間,建議設置爲2
#else
MAMTIM = 3; // 系統時鐘高於40M,建議設置爲3
#endif
MAMCR = 2; // 使能MAM
…}
LPC2400的外部存儲器控制器(EMC)是一個AMBA總線AHB從機模塊,它支持多種不一樣結構的存儲器,包括經常使用的異步靜態存儲器,如RAM、ROM和Flash等,也支持動態存儲器,如單數據率SDRAM等。EMC模塊能夠同時支持多達8個單獨配置的存儲器組,其中靜態存儲器和動態存儲器各4個Bank。靜態存儲器組由片選引腳CS0~CS3選中,每一個組存儲容量16MB,支持RAM、ROM、Flash和其它一些外部I/O部件,支持8位、16位和32位數據寬度。動態存儲器組由片選引腳DYCS0~DYCS3選中,每一個組存儲容量256MB,支持單數據率SDRAM,支持16位和32位數據寬度,刷新模式可由軟件控制。
1.EMC功能框圖和引腳信號
圖4.8 EMC功能框圖
表4.17 外部存儲器控制器引腳描述
引腳名稱 |
類 型 |
復位值 |
描 述 |
A[23:0] |
輸出 |
0x0000 0000 |
外部存儲器地址線。SDRAM存儲器只使用其中的位[14:0] |
D[31:0] |
輸入/輸出 |
0x0000 0000 |
外部存儲器數據線 |
OE |
輸出 |
1 |
靜態存儲器輸出使能信號,低電平有效 |
BLS[3:0] |
輸出 |
0x0F |
靜態存儲器字節定位選擇信號,低電平有效 |
WE |
輸出 |
1 |
寫使能信號,低電平有效 |
CS[3:0] |
輸出 |
0x0F |
靜態存儲器片選信號,低電平有效 |
DYCS[3:0] |
輸出 |
0x0F |
動態存儲器片選信號,低電平有效 |
CAS |
輸出 |
1 |
動態存儲器列地址選通訊號,低電平有效 |
RAS |
輸出 |
1 |
動態存儲器行地址選通訊號,低電平有效 |
CLKOUT[1:0] |
輸出 |
來自CCLK |
SDRAM時鐘 |
CKEOUT[3:0] |
輸出 |
0x0F |
SDRAM時鐘使能 |
DQMOUT[3:0] |
輸出 |
0x0F |
SDRAM輸出掩碼。也可用於靜態存儲器 |
2.外部存儲器接口
外部存儲器接口取決於存儲器組的數據寬度(32位、16位或8位,由EMCStaticConfig寄存器的MW位選擇)。若是一個存儲器組被配置爲32位寬度,地址線A0和A1能夠用作非地址線;若是存儲器組配置爲16爲寬度,則不須要A0;8位寬的存儲器組則須要使用A0。經過引腳鏈接模塊寄存器能夠實現A0和A1的地址或非地址功能。
圖4.9和圖4.10所示爲典型的32位總線寬度的存儲器組的外部存儲器接口硬件鏈接方式,其中符號「a_b」表示數據總線的最高位地址線,符號「a_m」表示使用外部存儲器接口的存儲器芯片的最高位地址線。
圖4.9中,一個32位寬度的存儲器組由4個8位存儲器芯片擴展而成,所以這4個芯片用同一個片選信號CS選中有效,同時使用同一個寫使能信號OE。第一個存儲器芯片構成存儲器組32位中的高8位,所以其寫使能信號WE鏈接到字節選擇信號的最高位BLS[3],8位數據線鏈接到數據總線的最高8位D[31:24]。其他三個芯片分別構成32位存儲器組中的第2、3、4個字節。因爲存儲器組的數據寬度爲32位,地址總線中的A0和A1不使用,只使用最高位a_b到bit2鏈接到存儲芯片的地址線上。
圖4.10中的16位芯片引腳UB和LB分別表示芯片中16位數據的高字節和低字節。32位芯片中的引腳B3~B0表示芯片中32位數據的四個字節。其芯片引腳與總線的鏈接方式與圖4.9是相似的。
按照圖4.9和圖4.10的方法,讀者不可貴出16位和8位總線寬度的存儲器組的外部存儲器接口擴展方法。
圖4.9 4個8位靜態存儲器芯片構成32位寬存儲器組
圖4.10 2個16位存儲器芯片和1個32位存儲器芯片構成32位寬存儲器組
圖4.11所示爲使用SDRAM芯片構成32位動態存儲器組的外部存儲器接口鏈接方法。圖中使用的SDRAM芯片爲K4S561632H,這款芯片的存儲容量爲256Mb,32位寬度,存儲空間分爲4個組,使用時由組選擇信號BA0和BA1選擇。在連線時,除了要注意使用與靜態存儲器不一樣的動態存儲器引腳如DYCS、CLKOUT、CKEOUT和DQMOUT以外,要格外注意地址線的連法。LPC2400的SDRAM地址線只使用地址線中的[14:0]這15根線,最高位兩根A14和A13固定鏈接到芯片的組選擇信號BA1和BA0,其他地址線從A0開始一一鏈接。這種鏈接方式是LPC2400的EMC特有的,與其它的ARM芯片,如三星的S3C系列芯片有很大區別,開發者在本身擴展SDRAM存儲器時必定要特別注意。
圖4.11 外部擴展存儲器接口SDRAM
3.EMC相關寄存器
表4.18所示爲EMC的相關寄存器。
表4.18 EMC寄存器彙總
寄存器名 |
類型 |
復位值 |
功能描述 |
地址 |
EMCControl |
讀/寫 |
0x3 |
EMC控制操做 |
0xFFE0 8000 |
EMCStatus |
只讀 |
0x5 |
提供EMC控制信息 |
0xFFE0 8004 |
EMCConfig |
讀/寫 |
0x0 |
EMC配置操做 |
0xFFE0 8008 |
EMCDynamic Control |
讀/寫 |
0x6 |
控制動態存儲器操做 |
0xFFE0 8020 |
EMCDynamic Refresh |
讀/寫 |
0x0 |
配置動態存儲器刷新操做 |
0xFFE0 8024 |
EMCDynamicReadConfig |
讀/寫 |
0x0 |
配置動態存儲器讀策略 |
0xFFE0 8028 |
EMCDynamicRP |
讀/寫 |
0x0F |
選擇預充電命令週期 |
0xFFE0 8030 |
EMCDynamicRAS |
讀/寫 |
0x0F |
選擇激活預充電命令週期 |
0xFFE0 8034 |
EMCDynamicSREX |
讀/寫 |
0x0F |
選擇刷新退出時間 |
0xFFE0 8038 |
EMCDynamicAPR |
讀/寫 |
0x0F |
選擇最後數據輸出激活命令時間 |
0xFFE0 803C |
EMCDynamicDAL |
讀/寫 |
0x0F |
選擇數據輸入激活命令時間 |
0xFFE0 8040 |
EMCDynamicWR |
讀/寫 |
0x0F |
選擇寫修復時間 |
0xFFE0 8044 |
EMCDynamicRC |
讀/寫 |
0x1F |
選擇激活有效命令週期 |
0xFFE0 8048 |
EMCDynamicRFC |
讀/寫 |
0x1F |
選擇自動刷新週期 |
0xFFE0 804C |
EMCDynamicXSR |
讀/寫 |
0x1F |
選擇退出刷新有效命令時間 |
0xFFE0 8050 |
EMCDynamicRRD |
讀/寫 |
0x0F |
選擇激活組A到組B延遲 |
0xFFE0 8054 |
EMCDynamicMRD |
讀/寫 |
0x0F |
選擇有效命令時間的加載模式寄存器 |
0xFFE0 8058 |
EMCDynamicConfig0 |
讀/寫 |
0x0 |
選擇動態存儲器芯片0配置信息 |
0xFFE0 8100 |
EMCDynamicRasCas0 |
讀/寫 |
0x303 |
選擇動態存儲器芯片0RASCAS延遲 |
0xFFE0 8104 |
EMCDynamicConfig1 |
讀/寫 |
0x0 |
選擇動態存儲器芯片0配置信息 |
0xFFE0 8120 |
EMCDynamicRasCas1 |
讀/寫 |
0x303 |
選擇動態存儲器芯片0RASCAS延遲 |
0xFFE0 8124 |
EMCDynamicConfig2 |
讀/寫 |
0x0 |
選擇動態存儲器芯片0配置信息 |
0xFFE0 8140 |
EMCDynamicRasCas2 |
讀/寫 |
0x303 |
選擇動態存儲器芯片0RASCAS延遲 |
0xFFE0 8144 |
EMCDynamicConfig3 |
讀/寫 |
0x0 |
選擇動態存儲器芯片0配置信息 |
0xFFE0 8160 |
EMCDynamicRasCas3 |
讀/寫 |
0x303 |
選擇動態存儲器芯片0RASCAS延遲 |
0xFFE0 8164 |
EMCStaticConfig0 |
讀/寫 |
0x0 |
選擇靜態存儲器芯片0配置 |
0xFFE0 8200 |
EMCStaticWaitWen0 |
讀/寫 |
0x0 |
選擇寫使能芯片0延遲 |
0xFFE0 8204 |
EMCStaticWaitOen0 |
讀/寫 |
0x0 |
選擇輸出使能芯片0延遲 |
0xFFE0 8208 |
EMCStaticWaitRd0 |
讀/寫 |
0x0 |
選擇讀訪問芯片0延遲 |
0xFFE0 820C |
EMCStaticWaitPage0 |
讀/寫 |
0x1F |
選擇芯片0異步頁模式順序訪問延遲 |
0xFFE0 8210 |
EMCStaticWaitWr0 |
讀/寫 |
0x1F |
選擇寫訪問芯片0延遲 |
0xFFE0 8214 |
EMCStaticWaitTurn0 |
讀/寫 |
0x0F |
選擇芯片0總線翻轉週期 |
0xFFE0 8218 |
EMCStaticConfig1 |
讀/寫 |
0x0 |
選擇靜態存儲器芯片1配置 |
0xFFE0 8220 |
EMCStaticWaitWen1 |
讀/寫 |
0x0 |
選擇寫使能芯片1延遲 |
0xFFE0 8224 |
EMCStaticWaitOen1 |
讀/寫 |
0x0 |
選擇輸出使能芯片1延遲 |
0xFFE0 8228 |
EMCStaticWaitRd1 |
讀/寫 |
0x0 |
選擇讀訪問芯片1延遲 |
0xFFE0 822C |
EMCStaticWaitPage1 |
讀/寫 |
0x1F |
選擇芯片1異步頁模式順序訪問延遲 |
0xFFE0 8230 |
EMCStaticWaitWr1 |
讀/寫 |
0x1F |
選擇寫訪問芯片1延遲 |
0xFFE0 8234 |
EMCStaticWaitTurn1 |
讀/寫 |
0x0F |
選擇芯片1總線翻轉週期 |
0xFFE0 8238 |
EMCStaticConfig2 |
讀/寫 |
0x0 |
選擇靜態存儲器芯片2配置 |
0xFFE0 8240 |
EMCStaticWaitWen2 |
讀/寫 |
0x0 |
選擇寫使能芯片2延遲 |
0xFFE0 8244 |
EMCStaticWaitOen2 |
讀/寫 |
0x0 |
選擇輸出使能芯片2延遲 |
0xFFE0 8248 |
EMCStaticWaitRd2 |
讀/寫 |
0x0 |
選擇讀訪問芯片2延遲 |
0xFFE0 824C |
EMCStaticWaitPage2 |
讀/寫 |
0x1F |
選擇芯片2異步頁模式順序訪問延遲 |
0xFFE0 8250 |
EMCStaticWaitWr2 |
讀/寫 |
0x1F |
選擇寫訪問芯片2延遲 |
0xFFE0 8254 |
EMCStaticWaitTurn2 |
讀/寫 |
0x0F |
選擇芯片2總線翻轉週期 |
0xFFE0 8258 |
EMCStaticConfig3 |
讀/寫 |
0x0 |
選擇靜態存儲器芯片3配置 |
0xFFE0 8260 |
EMCStaticWaitWen3 |
讀/寫 |
0x0 |
選擇寫使能芯片3延遲 |
0xFFE0 8264 |
EMCStaticWaitOen3 |
讀/寫 |
0x0 |
選擇輸出使能芯片3延遲 |
0xFFE0 8268 |
EMCStaticWaitRd3 |
讀/寫 |
0x0 |
選擇讀訪問芯片3延遲 |
0xFFE0 826C |
EMCStaticWaitPage3 |
讀/寫 |
0x1F |
選擇芯片3異步頁模式順序訪問延遲 |
0xFFE0 8270 |
EMCStaticWaitWr3 |
讀/寫 |
0x1F |
選擇寫訪問芯片3延遲 |
0xFFE0 8274 |
EMCStaticWaitTurn3 |
讀/寫 |
0x0F |
選擇芯片3總線翻轉週期 |
0xFFE0 8278 |
EMCStaticExtendedWait |
讀/寫 |
0x0 |
靜態存儲器讀寫傳輸時間 |
0xFFE0 8880 |
各寄存器的詳細配置方法,因爲篇幅所限,再也不贅述。在對系統進行外擴存儲器開發時,須要仔細閱讀外擴存儲器芯片的相關文檔,得到其準確的配置參數,再在初始化函數中對相關寄存器進行配置操做,才能正常使用外擴存儲器。
系統控制模塊包括幾個系統特性和控制寄存器,這些寄存器具備許多與特定外設器件無關的功能,每種類型的功能都有其自身的寄存器。
表4.19所示位系統控制和狀態寄存器(System Controls and Status register)。
表4.19 系統控制和狀態寄存器(SCS – 0xE01F C1A0)
位 |
標識 |
值 |
功能描述 |
類型 |
復位值 |
0 |
GPIOM |
|
GPIO訪問模式選擇 |
讀/寫 |
0 |
0 |
GPIO組0和組1配置爲與之前的LPC2000系列兼容的端口 |
||||
1 |
GPIO組0和組1配置爲高速端口,使用片內存儲器 |
||||
位 |
標識 |
值 |
功能描述 |
類型 |
復位值 |
1 |
EMC Reset Disable |
|
外部存儲器控制器復位無效 |
讀/寫 |
0 |
0 |
復位時,EMC的全部寄存器和功能從新初始化 |
||||
1 |
只有上電和掉電時EMC從新初始化 |
||||
2 |
|
|
保留 |
|
|
3 |
MCIPWR Active Level |
|
MCIPWR有效電平 |
讀/寫 |
0 |
0 |
MCIPWR引腳低電平 |
||||
1 |
MCIPWR引腳高電平 |
||||
4 |
OSCRANGE |
|
主晶振範圍選擇 |
讀/寫 |
0 |
0 |
主晶振頻率範圍從1MHz到20MHz |
||||
1 |
主晶振頻率範圍從15MHz到24MHz |
||||
5 |
OSCEN |
|
主晶振使能 |
讀/寫 |
0 |
0 |
主晶振無效 |
||||
1 |
主晶振有效 |
||||
6 |
OSCSTAT |
|
主晶振狀態 |
只讀 |
0 |
0 |
主晶振未準備好 |
||||
1 |
主晶振已準備好。能夠經過OSCEN位設置做爲一個時鐘源使用 |
||||
31:7 |
|
|
保留 |
|
NA |
SCS寄存器主要用於設置晶振使用方法和GPIO屬性,在後續相關章節裏會幾回使用到該寄存器。
1. 邏輯結構
LPC2400含有4個外部中斷輸入(做爲可選的管腳功能),四個引腳分別爲EINT0、EINT1、EINT2和EINT3。外部中斷輸入可用於將處理器從掉電模式喚醒。
可將多個管腳同時鏈接同一路外部中斷,此時,外部中斷邏輯根據方式位和極性位的不一樣,分別進行以下處理:
1) 低有效電平激活方式,選用EINT功能的所有管腳的狀態都鏈接到一個正邏輯與門。
2) 高有效電平激活方式,選用EINT功能的所有管腳的狀態都鏈接到一個正邏輯或門。
3) 邊沿激活方式,使用GPIO 端口號最低的管腳,與管腳的極性無關。(邊沿激活方式中選擇使用多個EINT管腳被看做編程出錯。)
外部中斷邏輯邏輯原理圖見圖4.12。
圖4.12 外部中斷邏輯原理圖
當多個EINT 管腳邏輯或時,可在中斷服務程序中經過IO0PIN和IO1PIN寄存器從GPIO端口讀出管腳狀態來判斷產生中斷的管腳。
2. 寄存器描述
外部中斷具備4 個相關的寄存器,如表4.20所示。EXTINT寄存器包含中斷標誌,INTWAKE寄存器包含使能喚醒位,可以使能獨立的外部中斷輸入將處理器從掉電模式喚醒,EXTMODE和EXTPOLAR寄存器用來指定管腳使用電平或邊沿激活方式。
表4.20 外部中斷寄存器
地址 |
寄存器名 |
功能描述 |
類型 |
0xE01FC140 |
EXTINT |
外部中斷標誌寄存器,包含ENIT0、EINT1 、EINT2和EINT3的中斷標誌 |
讀/寫 |
0xE01FC144 |
INTWAKE |
中斷喚醒寄存器,指示哪些中斷能夠喚醒掉電的CPU,以及控制是否使能喚醒 |
讀/寫 |
0xE01FC148 |
EXTMODE |
外部中斷方式寄存器,控制每一個管腳的邊沿或電平激活 |
讀/寫 |
0xE01FC14C |
EXTPOLAR |
外部中斷極性寄存器,控制由每一個管腳的哪一種電平或邊沿來產生中斷 |
讀/寫 |
1) 外部中斷標誌寄存器-External Interrupt Flag Register(EXTINT - 0xE01FC140)
當一個管腳選擇使用外部中斷功能時,對應在EXTPOLAR 和EXTMODE 寄存器中的位選擇的電平或邊沿將置位EXTINT寄存器中的中斷標誌,向VIC 提出中斷請求,若是管腳中斷使能,將會產生中斷。
向EXTINT 寄存器的位EINT0~位EINT3寫入1可清除相應的外部中斷標誌。在電平激活方式下,只有在該管腳處於無效狀態時才能清除相應的中斷標誌。
一旦EINT0~EINT3中的一位被置位並開始執行相應的代碼(處理喚醒和/或外部中斷),必須將該位清零,不然之後該EINT 管腳所觸發的事件將不能再被識別。
例如,若是外部中斷0 管腳的低電平將系統從掉電模式喚醒,爲了未來還能進入掉電模式,喚醒後的程序必須將EINT0位復位。若是EINT0位仍保持置位狀態,後來的喚醒掉電模式的任何操做都將失敗,外部中斷也不例外。
表4.21 外部中斷標誌寄存器
EXTINT |
功能 |
功能描述 |
復位值 |
0 |
EINT0 |
電平激活方式下,若是管腳的EINT0 功能被選用且管腳處於有效狀態時,該位置位;邊沿激活方式下,若是管腳的EINT0 功能被選用且管腳上出現所選極性,該位置位。 該位經過寫入1 清除,但電平激活方式下管腳處於有效狀態的狀況除外。 |
0 |
1 |
EINT1 |
電平激活方式下,若是管腳的EINT1 功能被選用且管腳處於有效狀態時,該位置位;邊沿激活方式下,若是管腳的EINT1 功能被選用且管腳上出現所選極性,該位置位。 該位經過寫入1 清除,但電平激活方式下管腳處於有效狀態的狀況除外。 |
0 |
2 |
EINT2 |
電平激活方式下,若是管腳的EINT2 功能被選用且管腳處於有效狀態時,該位置位;邊沿激活方式下,若是管腳的EINT2 功能被選用且管腳上出現所選極性,該位置位。 該位經過寫入1 清除,但電平激活方式下管腳處於有效狀態的狀況除外。 |
0 |
3 |
EINT3 |
電平激活方式下,若是管腳的EINT3 功能被選用且管腳處於有效狀態時,該位置位;邊沿激活方式下,若是管腳的EINT3 功能被選用且管腳上出現所選極性,該位置位。 該位經過寫入1 清除,但電平激活方式下管腳處於有效狀態的狀況除外。 |
0 |
7:4 |
|
保留 |
NA |
2) 中斷喚醒寄存器-Interrupt Wakeup Register(INTWAKE - 0xE01FC144)
INTWAKE寄存器(有時亦稱爲EXTWAKE,外部中斷喚醒寄存器)中的使能位容許外部中斷、以太網、USB、CAN、GPIO、BOD或者RTC中斷將處理器從掉電模式喚醒。相關的EINTn功能必須映射到管腳才能實現掉電喚醒,但中斷並沒必要要爲了實現喚醒操做而在向量中斷控制器中被使能。這樣作的好處是容許外部中斷輸入將處理器從掉電模式喚醒,但不產生中斷(只是簡單地恢復操做),或者在掉電模式下使能中斷而不將處理器喚醒(這樣,當應用中並不須要喚醒特性時,也沒必要關閉中斷)。
表4.22 外部中斷喚醒寄存器
INTWAKE |
功能 |
功能描述 |
復位值 |
0 |
EXTWAKE0 |
該位爲1 時,使能EINT0將處理器從掉電模式喚醒 |
0 |
1 |
EXTWAKE1 |
該位爲1 時,使能EINT1將處理器從掉電模式喚醒 |
0 |
2 |
EXTWAKE2 |
該位爲1 時,使能EINT2將處理器從掉電模式喚醒 |
0 |
3 |
EXTWAKE3 |
該位爲3 時,使能EINT3將處理器從掉電模式喚醒 |
0 |
4 |
ETHWAKE |
該位爲1 時,使能以太網中斷將處理器從掉電模式喚醒 |
0 |
5 |
USBWAKE |
該位爲1 時,使能USB中斷將處理器從掉電模式喚醒 |
0 |
6 |
CANWAKE |
該位爲1 時,使能CAN總線中斷將處理器從掉電模式喚醒 |
0 |
7 |
GPIOWAKE |
該位爲1 時,使能特殊GPIO引腳中斷將處理器從掉電模式喚醒 |
0 |
13:8 |
|
保留 |
NA |
14 |
BODWAKE |
該位爲1 時,使能BOD中斷將處理器從掉電模式喚醒 |
0 |
15 |
RTCWAKE |
該位爲1 時,使能實時時鐘RTC中斷將處理器從掉電模式喚醒 |
0 |
要使器件進入掉電模式並容許總線或管腳上的一個或多個事件能使其恢復正常操做,軟件應該對管腳的外部中斷功能從新編程,選擇中斷合適的方式和極性以及掉電模式。喚醒時軟件應恢復管腳複用的外圍功能。
上述的全部總線或管腳都是低電平有效。若是軟件要使器件退出掉電模式來響應多個管腳共用的同一個EINTi 通道的事件,中斷通道必須編程設定爲低電平激活方式,由於只有在電平方式中通道才能使信號邏輯或來喚醒器件。
3)外部中斷方式寄存器-External Interrupt Mode Register(EXTMODE – 0xE01F C148)
EXTMODE寄存器中的位用來選擇每一個EINT腳是電平觸發仍是邊沿觸發。只有選擇用做EINT功能(經過管腳鏈接模塊)並已經過VICIntEnable(向量中斷使能寄存器)使能的管腳才能產生外部中斷(固然,若是管腳選擇用做其它功能,則可能產生其它功能的中斷)。
當某個中斷在VICIntEnable 中被禁止時,軟件應該只改變EXTMODE 寄存器中相應位的值。中斷從新使能前,軟件向EXTINT 寫入1 來清除EXTINT 位,EXTINT 位可經過改變激活方式來置位。
表4.23 外部中斷方式寄存器
EXTMODE |
功能 |
值 |
描述 |
復位值 |
0 |
EXTMODE0 |
0 |
EINT0 使用電平激活 |
0 |
1 |
EINT0 使用邊沿激活 |
|||
1 |
EXTMODE0 |
0 |
EINT0 使用電平激活 |
0 |
1 |
EINT0 使用邊沿激活 |
|||
2 |
EXTMODE0 |
0 |
EINT0 使用電平激活 |
0 |
1 |
EINT0 使用邊沿激活 |
|||
3 |
EXTMODE0 |
0 |
EINT0 使用電平激活 |
0 |
1 |
EINT0 使用邊沿激活 |
|||
7:4 |
|
|
保留 |
NA |
4) 外部中斷極性寄存器-External Interrupt Polarity Register(EXTPOLAR – 0xE01F C14C)
在電平激活方式中,EXTPOLAR寄存器用來選擇相應管腳是高電平仍是低電平有效;
在邊沿激活方式中,EXTPOLAR寄存器用來選擇管腳上升沿仍是降低沿有效。只有選擇用做EINT功能(經過管腳鏈接模塊)並已經過VICIntEnable(向量中斷使能寄存器)使能的管腳才能產生外部中斷(固然,若是管腳選擇用做其它功能,則可能產生其它功能的中斷)。
當某個中斷在VICIntEnable 中被禁止時,軟件應該只改變EXTPOLAR 寄存器中相應位的值。中斷從新使能前,軟件向EXTINT 寫入1 來清除EXTINT 位,EXTINT 位可經過改變中斷極性來置位。
表4.24 外部中斷極性寄存器
EXTPOLAR |
功能 |
值 |
描述 |
復位值 |
0 |
EXTPOLAR0 |
0 |
EINT0低電平或降低沿有效(由EXTMODE0決定) |
0 |
1 |
EINT0 高電平或上升沿有效(由EXTMODE0決定) |
|||
1 |
EXTPOLAR1 |
0 |
EINT1低電平或降低沿有效(由EXTMODE1決定) |
0 |
1 |
EINT1高電平或上升沿有效(由EXTMODE1決定) |
|||
2 |
EXTPOLAR2 |
0 |
EINT2低電平或降低沿有效(由EXTMODE2決定) |
0 |
1 |
EINT2高電平或上升沿有效(由EXTMODE2決定) |
|||
3 |
EXTPOLAR3 |
0 |
EINT3低電平或降低沿有效(由EXTMODE3決定) |
0 |
1 |
EINT3高電平或上升沿有效(由EXTMODE3決定) |
|||
7:4 |
|
|
保留 |
NA |
有關中斷向量、中斷設置與中斷服務子程序的內容詳見4.6節。
LPC2400含有3個獨立的晶體振盪器:主晶振、內部RC晶振和RTC晶振。每一個晶振針對不一樣應用需求有多種使用方法。復位後,LPC2400系列處理器使用內部RC晶振提供時鐘進行操做,直到使用軟件進行切換爲止。這使得系統能夠不依賴於外部時鐘進行操做,並且使引導加載程序能夠在一個肯定的頻率下進行操做。當Boot ROM轉向用戶程序以前,能夠激活主晶振從而進入用戶代碼。
1.內部晶體振盪器(IRC,Internal RC Oscillator)
IRC能夠用作看門狗定時器的時鐘源,也能夠做爲時鐘,驅動PLL鎖相環提供給CPU。IRC的精度不夠,所以不能用於USB接口。一般的IRC頻率是4MHz。在開機或芯片復位時,LPC2400使用IRC做爲時鐘源,以後能夠使用軟件轉爲使用其它時鐘源。
2.主晶振(Main Oscillator)
主晶振可用於爲CPU提供時鐘,其頻率範圍爲1MHz~24MHz。這個頻率能夠經過PLL倍頻爲更高的頻率成爲CPU的主頻。一般把主晶振輸出的時鐘稱爲OSCCLK,PLL輸入引腳上的時鐘稱爲PLLCLKIN,ARM處理器內核時鐘頻率稱爲CCLK。當使用主晶振提供時鐘而不激活PLL時,這三個值是相等的。
因爲芯片復位時使用IRC晶振,主晶振由軟件啓動(使用SCS寄存器中的OSCEN位),而且在某些應用中始終不會用到。經過SCS寄存器中的OSCSTAT狀態位能夠使軟件判斷主晶振是否運行和穩定,也能夠經過SCS寄存器中的OSCRANGE位設置其頻率範圍。
LPC2400的振盪器可工做在兩種模式下:從屬模式和振盪模式。從屬模式下,輸入時鐘信號XTAL1與一個100pF相連,其幅值很多於200mV,XTAL2管腳不鏈接。振盪模式下,因爲片內集成了反饋電阻,只需在外部鏈接一個晶體和電容Cx1、Cx2 就可造成基本模式的振盪。
兩種振盪器模式的示意見圖4.13。
圖4.13 振盪器模式
3.RTC晶振(RTC Oscillator)
RTC晶振的頻率爲32.768KHz,通常用於給RTC實時時鐘提供時鐘源。RTC晶振也能夠用於看門狗定時器,經過驅動PLL也能夠用於提供CPU主頻。
4.時鐘源選擇
幾個時鐘源均可以用來驅動PLL從而給CPU和片內外設提供時鐘。當PLL未鏈接時,系統能夠經過CLKSRCSEL寄存器安全的改變時鐘源。
表4.25 時鐘源選擇寄存器(CLKSRCSEL – 0xE01F C10C)
CLKSRCSEL |
功能 |
值 |
描述 |
復位值 |
1:0 |
CLKSRC |
00 |
選擇IRC晶振爲PLL時鐘源 |
00 |
01 |
選擇主晶振爲PLL時鐘源 |
|||
10 |
選擇RTC晶振爲PLL時鐘源 |
|||
11 |
保留 |
|||
7:4 |
|
0 |
未使用,始終爲0 |
0 |
PLL接受輸入的時鐘頻率範圍爲32kHz~50MHz。輸入頻率經過一個預分頻器分頻成爲PLL內部頻率,預分頻器的值用變量「N」表示。而後再經過一個電流控制振盪器(CCO)倍增到範圍275MHz~550MHz,倍頻器的值用變量「M」表示。CCO頻率再經過CPU頻率設置寄存器分頻成爲提供給CPU的CCLK時鐘。
PLL 的激活由PLLCON寄存器控制,PLL倍頻器和分頻器的值由PLLCFG寄存器控制。爲了防止PLL參數發生意外改變或PLL失效,對這兩個寄存器進行了保護。當PLL提供芯片時鐘時,因爲芯片的全部操做,包括看門狗定時器在內都依賴於它,所以PLL設置的意外改變將致使CPU 執行不指望的動做。
1.PLL控制寄存器-PLL Control Register(PLLCON – 0xE01FC080)
PLLCON寄存器可用於使能和鏈接PLL,它是最新的PLL控制位的保持寄存器,寫入該寄存器的值在有效的PLL 饋送序列執行以前不起做用。使能PLL將使PLL鎖定到當前倍頻器和分頻器值的設定頻率上。鏈接PLL將使處理器和全部片內功能都根據PLL輸出時鐘來運行。對PLLCON的更改只有在對PLLFEED寄存器執行了正確的PLL饋送序列後才生效。
表4.26 PLL 控制寄存器
PLLCON |
功能 |
描述 |
復位值 |
0 |
PLLE |
PLL使能。當該位爲1 而且在有效的PLL饋送以後,該位將激活PLL並容許其鎖定到指定的頻率。 |
0 |
1 |
PLLC |
PLL鏈接。當PLLC和PLLE都爲1 而且在有效的PLL饋送後,將PLL做爲時鐘源鏈接到LPC2400。不然,LPC2400直接使用振盪器時鐘。 |
0 |
7:2 |
保留 |
保留 |
NA |
PLL在做爲時鐘源以前必須進行設置、使能並鎖定。將振盪器時鐘切換到PLL輸出或反過來操做時,內部電路對操做進行同步以確保不會產生干擾。硬件不能確保PLL在鏈接以前鎖定或在PLL在失去鎖定時自動斷開鏈接。在PLL失去鎖定的狀況下,振盪器極可能已經變得不穩定,這樣即便斷開PLL也挽救不了這種情況。
2.PLL配置寄存器-PLL Configuration Register(PLLCFG – 0xE01FC084)
PLLCFG寄存器是最新的PLL配置值的保持寄存器,包含PLL倍頻器和分頻器值。在執行正確的PLL饋送序列以前改變PLLCFG寄存器的值不會生效。
表4.27 PLL配置寄存器
PLLCFG |
功能 |
描述 |
復位值 |
14:0 |
MSEL |
PLL倍頻器值,在PLL頻率計算中其值爲M-1 |
0 |
15 |
保留 |
保留 |
NA |
23:16 |
NSEL |
PLL預分配器值,在PLL頻率計算中其值爲N |
NA |
31:24 |
保留 |
保留 |
NA |
3.PLL狀態寄存器-PLL Status Register(PLLSTAT – 0xE01FC088)
PLLSTAT爲只讀寄存器,它是PLL控制和配置信息的讀回寄存器,反映了正在使用的真實PLL參數和狀態。PLLSTAT可能與PLLCON和PLLCFG中的值不一樣,這是由於沒有執行正確的PLL饋送序列,這兩個寄存器中的值並未生效。
表4.28 PLL狀態寄存器
PLLSTAT |
功能 |
描述 |
復位值 |
14:0 |
MSEL |
讀出的PLL倍頻器值,這是PLL當前使用的值 |
0 |
15 |
保留 |
保留 |
NA |
23:16 |
NSEL |
讀出的PLL預分頻器值,這是PLL當前使用的值 |
NA |
24 |
PLLE |
讀出的PLL使能位,該位爲1時,PLL處於激活狀態;爲0時,PLL關閉;進入掉電模式時,該位自動清零 |
0 |
25 |
PLLC |
讀出的PLL鏈接位,當PLLC和PLLE都爲1 時,PLL做爲時鐘源鏈接到LPC2400;當PLLC或PLLE位爲0 時,PLL被旁路,LPC2400直接使用振盪器時鐘;進入掉電模式時,該位自動清零 |
0 |
26 |
PLOCK |
反映PLL的鎖定狀態,爲0時,PLL未鎖定;爲1時,PLL鎖定到指定的頻率 |
|
31:27 |
保留 |
保留 |
NA |
PLLSTAT 寄存器中的PLOCK位鏈接到中斷控制器。這樣可以使用軟件打開PLL並鏈接到其它功能,不須要等待PLL鎖定。當發生中斷時(PLOCK=1),能夠鏈接PLL並禁止中斷。只能經過禁止PLL中斷的方式返回。
PLL有3種可能的工做模式,由PLLE和PLLC組合獲得。
表4.29 PLL的工做模式
PLLC |
PLLE |
PLL 功能 |
0 |
0 |
PLL 被關閉並斷開鏈接,系統使用未更改的時鐘輸入 |
0 |
1 |
PLL 被激活可是還沒有鏈接,PLL 可在PLOCK 置位後鏈接 |
1 |
0 |
與00 組合相同,這樣消除了PLL 已鏈接但沒有使能的可能性 |
1 |
1 |
PLL 已使能並鏈接處處理器做爲系統時鐘源 |
4.PLL饋送寄存器-PLL Feed Register(PLLFEED – 0xE01FC08C)
必須將正確的饋送序列寫入PLLFEED寄存器才能使PLLCON和PLLCFG寄存器的更改生效。饋送序列以下:
1) 將值0xAA 寫入PLLFEED;
2) 將值0x55 寫入PLLFEED。
這兩個寫操做的順序必須正確,並且必須是連續的APB總線週期,這意味着在執行PLL饋送操做時必須禁止中斷。無論是寫入的值不正確仍是沒有知足前兩個條件,對PLLCON或PLLCFG寄存器的更改都不會生效。
表4.30 PLL 饋送寄存器
PLLFEED |
功能 |
描述 |
復位值 |
7:0 |
PLLFEED |
PLL饋送序列必須寫入該寄存器才能使PLL配置和控制寄存器的更改生效 |
0x00 |
5.PLL和掉電模式
掉電模式會自動關閉並斷開PLL。從掉電模式喚醒不會自動恢復PLL的設定,PLL的恢復必須由軟件來完成。一般,一個將PLL激活並等待鎖定,而後將PLL鏈接的子程序能夠在任何中斷服務程序的開始調用。有一點很是重要,那就是不要試圖在掉電喚醒以後簡單地執行饋送序列來從新啓動PLL,這會出如今PLL鎖定創建以前同時使能並鏈接PLL的危險。
6.PLL頻率計算舉例:
當一個LPC2400 ARM系統須要使用PLL,應當按照如下原則進行:
1) 肯定處理器的時鐘頻率CCLK。這能夠根據系統對處理器的總體要求來決定,外圍器件的時鐘頻率能夠低於處理器頻率。
2) 肯定PLL內部的時鐘頻率FCCO。FCCO的值應當在275MHz~550MHz之間,並且應當是CCLK的整數倍。
3) 肯定晶體振盪器頻率FIN。FIN的值應當在32kHz~50MHz之間。
PLL的輸出頻率公式爲:FCCO = (2×M×FIN) / N
選擇兩個整數M和N即可獲得合適的FCCO值。M的取值範圍爲6~512,N的取值範圍爲1~32。
例如:系統要求使用USB接口,CPU主頻約爲60MHz。外部晶振頻率爲4MHz。
由要求可知:USB總線要求精確的48MHz時鐘,所以能夠選擇FCCO爲480MHz。當N值爲1時,M = 480 / (2×4) = 60。所以PLLCFG值爲0x3B(N-1 = 0,M-1 = 0x3B)。
PLL的輸出必須向下分頻爲更低頻率的信號才能用於CPU和USB模塊。提供給USB模塊的分頻器是獨立的,由於USB的時鐘要求必須是準確的48MHz並且有50%的佔空比。分頻給CPU的信號成爲CCLK時鐘,而且再分頻成爲各個片內外設的驅動時鐘。
1.CPU時鐘配置寄存器-CPU Clock Configuration Register(CCLKCFG – 0xE01F C104)
CCLKCFG寄存器控制PLL的分頻輸出提供給CPU。若是不使用PLL,分頻值爲1。
表4.31 CPU時鐘配置寄存器
CCLKCFG |
功能 |
描述 |
復位值 |
7:0 |
CCLKSEL |
分頻器值,用於生成CPU時鐘(CCLK)。本值只能爲0或奇數值(1,3,5,…,255) |
0x00 |
CCLK值爲PLL的輸出頻率除以CCLKSEL+1。當CCLKSEL值爲1時,CCLK值爲PLL輸出頻率的一半。
2.USB時鐘配置寄存器-USB Clock Configuration Register(USBCLKCFG – 0xE01F C108)
USBCLKCFG寄存器控制PLL的分頻輸出提供給USB模塊。若是不使用PLL,分頻值爲1。輸出的頻率應該爲48MHz而且有50%的佔空比。
表4.32 USB時鐘配置寄存器
USBCLKCFG |
功能 |
描述 |
復位值 |
3:0 |
USBSEL |
分頻器值,用於生成USB時鐘(CCLK) |
0x00 |
7:4 |
- |
保留 |
NA |
USB模塊的時鐘值爲PLL的輸出頻率除以USBSEL+1。當USBSEL值爲1時,USB時鐘值爲PLL輸出頻率的一半。
3.IRC整理寄存器-IRC Trim Register(IRCTRIM – 0xE01F C1A4)
這個寄存器用於整理片內4MHz的晶振。
表4.33 IRC整理寄存器
IRCtrim |
功能 |
描述 |
復位值 |
7:0 |
IRCtrim |
IRC整理值,用於控制片內4MHzIRC晶振頻率 |
0xA0 |
15:8 |
- |
保留 |
NA |
4.外設時鐘選擇寄存器0和1-Peripheral Clock Selection registers 0 and 1(PCLKSEL0 – 0xE01F C1A8 and PCLKSEL1 – 0xE01F C1AC)
這一對寄存器中的每兩位控制一個外設的時鐘,其取值意義參見表4.36。
表4.34 外設時鐘選擇寄存器0
PCLKSEL0 |
功能 |
描述 |
復位值 |
1:0 |
PCLK_WDT |
看門狗外設時鐘選擇 |
00 |
3:2 |
PCLK_TIMER0 |
定時器0外設時鐘選擇 |
00 |
5:4 |
PCLK_TIMER1 |
定時器1外設時鐘選擇 |
00 |
7:6 |
PCLK_UART0 |
串口0外設時鐘選擇 |
00 |
9:8 |
PCLK_UART1 |
串口1外設時鐘選擇 |
00 |
11:10 |
PCLK_PWM0 |
脈寬調製器0外設時鐘選擇 |
00 |
13:12 |
PCLK_PWM1 |
脈寬調製器1外設時鐘選擇 |
00 |
15:14 |
PCLK_I2C0 |
I2C0外設時鐘選擇 |
00 |
17:16 |
PCLK_SPI |
SPI外設時鐘選擇 |
00 |
19:18 |
PCLK_RTC |
實時時鐘外設時鐘選擇 |
00 |
21:20 |
PCLK_SSP1 |
SSP1外設時鐘選擇 |
00 |
23:22 |
PCLK_DAC |
DAC外設時鐘選擇 |
00 |
25:24 |
PCLK_ADC |
ADC外設時鐘選擇 |
00 |
27:26 |
PCLK_CAN1 |
CAN1外設時鐘選擇 |
00 |
29:28 |
PCLK_CAN2 |
CAN2外設時鐘選擇 |
00 |
31:30 |
PCLK_ACF |
CAN濾波器外設時鐘選擇 |
00 |
注:PCLK_RTC字段中,值「01」是無效的,試圖寫入「01」不會改變預設值。
表4.35 外設時鐘選擇寄存器1
PCLKSEL1 |
功能 |
描述 |
復位值 |
1:0 |
PCLK_BAT_RAM |
電池支持RAM外設時鐘選擇 |
00 |
3:2 |
PCLK_GPIO |
GPIO外設時鐘選擇 |
00 |
5:4 |
PCLK_PCB |
引腳鏈接模塊外設時鐘選擇 |
00 |
7:6 |
PCLK_I2C1 |
I2C1外設時鐘選擇 |
00 |
9:8 |
- |
保留,始終爲0 |
00 |
11:10 |
PCLK_SSP0 |
SSP0外設時鐘選擇 |
00 |
13:12 |
PCLK_TIMER2 |
定時器2外設時鐘選擇 |
00 |
15:14 |
PCLK_TIMER3 |
定時器3外設時鐘選擇 |
00 |
17:16 |
PCLK_UART2 |
串口2外設時鐘選擇 |
00 |
19:18 |
PCLK_UART3 |
串口3外設時鐘選擇 |
00 |
21:20 |
PCLK_I2C2 |
I2C2外設時鐘選擇 |
00 |
23:22 |
PCLK_I2S |
I2S總線外設時鐘選擇 |
00 |
25:24 |
PCLK_MCI |
MCI外設時鐘選擇 |
00 |
27:26 |
- |
保留,始終爲0 |
00 |
PCLKSEL1 |
功能 |
描述 |
復位值 |
29:28 |
PCLK_SYSCON |
系統控制模塊外設時鐘選擇 |
00 |
31:30 |
- |
保留,始終爲0 |
00 |
表4.36 外設時鐘選擇寄存器位值
位 |
功能描述 |
復位值 |
00 |
PCLK_xxx = CCLK / 4 |
00 |
01 |
PCLK_xxx = CCLK |
00 |
10 |
PCLK_xxx = CCLK / 2 |
00 |
11 |
在CAN1、CAN2、CAN濾波器部件中PCLK_xxx = HCLK / 6,其他部件中PCLK_xxx = HCLK / 8 |
00 |
1. 節電模式
嵌入式系統通常使用電池供電,所以系統的耗電和待機時間是個重要指標。節電的方法主要是下降系統時鐘頻率:改變時鐘源、重配置PLL值或者改變CPU時鐘分頻值。另外,也能夠經過中止片內外設時鐘的方法來關閉不使用的片內外設,進一步減小功耗。
LPC2400支持三種節電模式:空閒模式、睡眠模式和掉電模式。LPC2400有一個獨立的功率控制單元用來給RTC和一個小的靜態RAM供電,這個特性使得LPC2400能夠將片內的其它大部分設備所有關閉。
1)空閒模式(Idel mode):指令的執行被掛起直到發生復位或中斷爲止。外設功能在空閒模式下繼續保持並可產生中斷使處理器恢復運行。空閒模式使處理器、存儲器系統和相關控制器以及內部總線再也不消耗功率。任何中斷均可以將CPU從空閒模式下喚醒。
2)睡眠模式(Sleep mode):主晶振關閉,全部時鐘中止。IRC的輸出無效,但IRC並未關閉而且能夠快速喚醒。32kHz的RTC晶振也未中止,由於RTC中斷能夠用來作喚醒的中斷源。睡眠模式保持處理器狀態和寄存器、外設寄存器和內部SRAM的值。芯片管腳的邏輯電平保持靜態。復位或特定的不須要時鐘仍能工做的中斷可停止睡眠模式並使芯片恢復正常運行。因爲睡眠模式使芯片全部的動態操做都掛起,所以芯片的功耗下降到幾乎爲零。芯片復位和特定的中斷能夠將CPU從睡眠模式下喚醒。
3)掉電模式(Power-down mode):掉電模式與睡眠模式相似,但不一樣的是掉電模式會將Flash存儲器也關閉。在掉電模式下,主晶振和IRC以及全部內部時鐘都中止,只有32kHz的RTC晶振繼續工做。
2. 寄存器描述
外設的功率控制特性容許獨立關閉應用中不須要的外設,這樣能夠進一步下降功耗。功率控制功能包含兩個寄存器,分別是PCON和PCONP。
1) 功率控制寄存器-Power Control Register(PCON – 0xE01F C0C0)
表4.37 功率控制寄存器
PCON |
功能 |
描述 |
復位值 |
0 |
PM0(IDL) |
功耗模式控制位0 |
0 |
1 |
PM1(PD) |
功耗模式控制位1 |
0 |
2 |
BODPDM |
低電壓掉電模式。當該位爲0時,進入掉電模式時仍然保持低電壓檢測功能;當該位爲1時,低電壓檢測功能也被關閉,這樣能夠進一步減小功耗,但存在着電壓太低而沒法從掉電模式中喚醒的可能 |
0 |
3 |
BOGD |
低電壓全局無效。當該位爲1時,低電壓檢測功能無效;該位爲0時,低電壓檢測功能使能 |
0 |
4 |
BORD |
低電壓復位無效。當該位爲1時,低電壓檢測(2.6V)不會致使芯片復位;當該位爲0時,低電壓檢測(2.9V)使芯片復位 |
0 |
6:3 |
- |
保留 |
NA |
7 |
PM2 |
功耗模式控制位2 |
0 |
利用PCON寄存器設置節電模式的方法詳見表4.38。PCON寄存器中的三個比特PM2、PM1和PM0聯合控制進入LPC2400節電模式的方式。
表4.38 節電模式控制位
PM2,PM1,PM0 |
功能描述 |
000 |
正常模式 |
001 |
空閒模式 |
101 |
睡眠模式 |
010 |
掉電模式 |
其它 |
保留 |
2)外設功率控制寄存器-Power Control for Peripherals Register(PCONP – 0xE01F C0C4)
PCONP寄存器容許將所選的外設功能關閉以實現節電的目的,經過關斷特定外圍模塊的時鐘源來實現。有少數外設功能不能被關閉(例如看門狗定時器、GPIO、引腳鏈接模塊和系統控制模塊)。
某些外設,特別是包含模擬功能的外設,它們的操做無需時鐘,但會消耗功率。這些外設包含獨立的禁能控制位,能夠經過它們來關閉電路以下降功耗。
PCONP中的每一個位都控制一個外設,每一個位所對應的外設編號見LPC2400存儲器尋址部分的APB外設映射一節。當位值爲1時該外設啓用,當位值爲0時該外設時鐘關閉。外設在外設功率控制寄存器的對應位見表4.11。
表4.39外設功率控制寄存器
PCONP |
功能 |
描述 |
復位值 |
0 |
- |
未使用,始終爲0 |
0 |
1 |
PCTIM0 |
定時器0功率時鐘控制位 |
1 |
2 |
PCTIM1 |
定時器1功率時鐘控制位 |
1 |
3 |
PCUART0 |
串口0功率時鐘控制位 |
1 |
4 |
PCUART1 |
串口1功率時鐘控制位 |
1 |
5 |
PCPWM0 |
脈寬調製器0功率時鐘控制位 |
1 |
6 |
PCPWM1 |
脈寬調製器1功率時鐘控制位 |
1 |
7 |
PCI2C0 |
I2C0功率時鐘控制位 |
1 |
8 |
PCSPI |
SPI功率時鐘控制位 |
1 |
9 |
PCRTC |
實時時鐘功率時鐘控制位 |
1 |
10 |
PCSSP1 |
SSP1接口功率時鐘控制位 |
1 |
11 |
PCEMC |
外擴存儲器控制器 |
1 |
12 |
PCAD |
A/D轉換器功率時鐘控制位。清零該位前先清零AD0CR 寄存器的PDN位,該位應當在置位PDN前被置位 |
0 |
13 |
PCCAN1 |
CAN1功率時鐘控制位 |
0 |
14 |
PCCAN2 |
CAN2功率時鐘控制位 |
0 |
18:15 |
- |
保留 |
NA |
19 |
PCI2C1 |
I2C1功率時鐘控制位 |
1 |
20 |
PCLCD |
液晶控制器功率時鐘控制位 |
0 |
21 |
PCSSP0 |
SSP0功率時鐘控制位 |
1 |
22 |
PCTIM2 |
定時器2功率時鐘控制位 |
0 |
23 |
PCTIM3 |
定時器3功率時鐘控制位 |
0 |
24 |
PCUART2 |
串口2功率時鐘控制位 |
0 |
25 |
PCUART3 |
串口3功率時鐘控制位 |
0 |
26 |
PCI2C2 |
I2C2功率時鐘控制位 |
1 |
27 |
PCI2S |
I2S接口功率時鐘控制位 |
0 |
28 |
PCSDC |
SD卡接口功率時鐘控制位 |
0 |
29 |
PCGPDMA |
通用DMA功能功率時鐘控制位 |
0 |
30 |
PCENET |
以太網模塊功率時鐘控制位 |
0 |
31 |
PCUSB |
USB接口功率時鐘控制位 |
0 |
復位之後,PCONP寄存器按照默認值使能選中的接口和外設控制器。用戶程序應當在啓動代碼中對PCONP寄存器編程用來啓動所須要的外設功能,並關閉不須要的接口和外設,以達到下降功耗的要求。系統啓動之後,除了對外設功能相關的寄存器進行配置外,用戶應用程序應當不要再訪問PCONP 寄存器從而啓動使用片內的任何外圍功能。
1. 系統時鐘設置
在LPC2400的啓動代碼中,系統時鐘的設置是經過一個ConfigurePLL ( )函數來實現的。該函數首先關閉PLL,而後經過CLKSRCSEL寄存器選擇主晶振爲時鐘源,再經過PLLCFG寄存器利用M值和N值設置CCO頻率,用CCLKCFG寄存器分頻爲CPU時鐘CCLK,最後使能PLL使設置生效。注意對PLLCON寄存器的每次操做都要用正確的饋送序列來實現。函數中的有關參數是在target.h頭文件中定義的,其相關程序行以下:
代碼清單4.2
……
#define Fosc 12000000
#define Fcclk 57600000
#define Fcco 288000000
#define Fpclk (Fcclk / 4)
#define PLL_MValue 11
#define PLL_NValue 0
#define CCLKDivValue 4
#define USBCLKDivValue 5
……
主晶振採用12MHz晶體振盪器,其宏定義Fosc值要跟實際的物理參數相同。因爲M值爲12,N值爲1(注意實際參數要在設置值上加1),CCO頻率Fcco = 2×M×Fosc / N = 288MHz。CPU時鐘CCLK = Fcco / (CCLKDivValue+1) = 57.6MHz。而USB時鐘USBCLK = Fcco / (USBCLKDivValue+1) = 48MHz,正好知足使用要求。
代碼清單4.3
void ConfigurePLL ( void )
{
if ( PLLSTAT & (1 << 25) ) // PLL是否鏈接
{ PLLCON = 1; // 使能PLL並斷開鏈接
PLLFEED = 0xaa; // PLL饋送
PLLFEED = 0x55; }
PLLCON = 0; // 關閉PLL並斷開鏈接
PLLFEED = 0xaa;
PLLFEED = 0x55;
SCS |= 0x20; // 使能主晶振
while( !(SCS & 0x40) ); // 讀主晶振狀態直到主晶振可用
CLKSRCSEL = 0x1; // 選擇12MHz主晶振做爲PLL時鐘源
PLLCFG = PLL_MValue | (PLL_NValue << 16); // 執行配置
PLLFEED = 0xaa;
PLLFEED = 0x55;
PLLCON = 1; // 使能PLL
PLLFEED = 0xaa;
PLLFEED = 0x55;
CCLKCFG = CCLKDivValue; // 設置時鐘分頻,設定CPU頻率CCLK
#if USE_USB
USBCLKCFG = USBCLKDivValue; // usbclk = 288 MHz/6 = 48 MHz
#endif
while ( ((PLLSTAT & (1 << 26)) == 0) ); // 檢查鎖定位狀態
PLLCON = 3; // 使能並鏈接PLL
PLLFEED = 0xaa;
PLLFEED = 0x55;
while ( ((PLLSTAT & (1 << 25)) == 0) ); // 檢查鏈接狀態位
return;
}
2. 外設分頻
外設啓動和分頻應在啓動代碼中實現。LPC2400的啓動代碼使用一個TargetResetInit( )函數實現,其中相關代碼以下:
代碼清單4.4
……
#if USE_USB
PCONP |= 0x80000000; // 若是使用USB則打開USB PCLK
#endif
ConfigurePLL();
#if (Fpclk / (Fcclk / 4)) == 1
PCLKSEL0 = 0x00000000; // PCLK = 1/4 CCLK
PCLKSEL1 = 0x00000000;
#endif
#if (Fpclk / (Fcclk / 4)) == 2
PCLKSEL0 = 0xAAAAAAAA; // PCLK = 1/2 CCLK
PCLKSEL1 = 0xAAAAAAAA;
#endif
#if (Fpclk / (Fcclk / 4)) == 4
PCLKSEL0 = 0x55555555; // PCLK = CCLK
PCLKSEL1 = 0x55555555;
#endif
……
爲了下降外設功耗,通常都將APB外設時鐘設爲CCLK時鐘的1/4。
3. 進入Idle模式
代碼清單4.5
……
PCON = 0x01; // 進入Idle狀態,CPU中止
……
進入Sleep模式和Power Down模式採用不一樣設置值進行設置便可。
LPC2400使用了ARM PrimeCellTM技術的向量中斷控制器,利用映射到AHB總線的地址空間實現快速訪問。支持最大32個向量IRQ中斷,擁有16個可編程中斷優先級,而且每一個可編程優先級對應固定硬件優先級,具備硬件優先級屏蔽邏輯。全部中斷均可設置爲FIQ中斷,還能夠產生軟件中斷。
ARM處理器內核有兩類中斷:中斷請求(IRQ)和快速中斷請求(FIQ)。管理中斷類型識別及優先級判斷,並向ARM內核提供中斷向量和中斷信號的模塊稱爲向量中斷控制器(VIC)。VIC支持的32箇中斷能夠編程設置爲IRQ或FIQ中斷類型。這樣用戶能夠按照處理器外圍模塊的優先級別靈活設置中斷的優先級別。
快速中斷請求(FIQ)是優先級最高的中斷。若是有一個以上中斷被設置爲FIQ,則VIC對中斷輸入進行「或」操做,最終向ARM內核產生一個FIQ信號。爲了確保FIQ響應的最短延時,在實際應用中通常只設置一箇中斷源爲FIQ類型。這樣FIQ中斷服務程序就能夠直接處理對應模塊。若是有多箇中斷源設置爲FIQ,則在FIQ中斷服務程序中要先讀出VIC的FIQ中斷狀態字,從而判斷真正發生的中斷源才能處理對應的中斷。
除了設置爲FIQ的中斷外,其他中斷類型爲向量IRQ。向量IRQ中斷優先級能夠編程設置。若是有一個以上IRQ中斷分配相同優先級且同時產生中斷請求,則鏈接到VIC的通道靠前的中斷源先被應答服務。VIC通道數值分配見中斷源小節表。
另外,VIC對全部向量IRQ進行「或」操做,最終向ARM內核產生一個IRQ信號。IRQ中斷服務程序先讀取VIC的IRQ中斷狀態字,肯定中斷源後執行相應中斷服務。
向量中斷控制器VIC的結構如圖4.14所示。
圖4.14 VIC的結構框圖
VIC內全部寄存器都爲32位寬,具體名稱及地址見表4.40。
表4.40 VIC寄存器映射表
名稱 |
功能描述 |
訪問方式 |
復位值[1] |
地址 |
VICIRQStatus |
IRQ中斷狀態寄存器。該寄存器保存各個IRQ中斷請求是否有效。 |
只讀 |
0 |
0xFFFFF000 |
VICFIQStatus |
FIQ中斷狀態寄存器。該寄存器保存各個FIQ中斷請求是否有效。 |
只讀 |
0 |
0xFFFFF004 |
VICRawIntr |
原始中斷狀態寄存器。該寄存器保存32箇中斷請求和軟件中斷是否有效,無論它們是否被使能。 |
只讀 |
- |
0xFFFFF008 |
VICIntSelect |
中斷類型選擇寄存器。該寄存器用於把中斷請求設置爲FIQ或者IRQ。 |
讀/寫 |
0 |
0xFFFFF00C |
VICIntEnable |
中斷使能寄存器。該寄存器使能32箇中斷請求和軟件中斷產生IRQ或FIQ中斷。 |
讀/寫 |
0 |
0xFFFFF010 |
VICIntEnClr |
中斷使能清除寄存器。該寄存器可清除中斷使能寄存器已使能的各中斷位。 |
只寫 |
- |
0xFFFFF014 |
VICSoftInt |
軟件中斷寄存器。該寄存器內容與32箇中斷請求做相「或」操做。 |
讀/寫 |
0 |
0xFFFFF018 |
名稱 |
功能描述 |
訪問方式 |
復位值[1] |
地址 |
VICSoftIntClear |
軟件中斷清除寄存器。 |
只寫 |
- |
0xFFFFF01C |
VICProtection |
VIC保護使能寄存器。該寄存器限制軟件在特權模式下運行時訪問VIC各個寄存器。 |
讀/寫 |
0 |
0xFFFFF020 |
VICSWPriorityMask |
軟件優先級屏蔽寄存器。 |
讀/寫 |
0xFFFF |
0xFFFFF024 |
VICVectAddr0 |
向量地址0寄存器。該寄存器保存IRQ0的中斷服務程序入口地址。IRQ0優先級最高,IRQ32最低。 |
讀/寫 |
0 |
0xFFFFF100 |
VICVectAddr1 |
向量地址1寄存器。 |
讀/寫 |
0 |
0xFFFFF104 |
VICVectAddr2 |
向量地址2寄存器。 |
讀/寫 |
0 |
0xFFFFF108 |
VICVectAddr3 |
向量地址3寄存器。 |
讀/寫 |
0 |
0xFFFFF10C |
VICVectAddr4 |
向量地址4寄存器。 |
讀/寫 |
0 |
0xFFFFF110 |
VICVectAddr5 |
向量地址5寄存器。 |
讀/寫 |
0 |
0xFFFFF114 |
VICVectAddr6 |
向量地址6寄存器。 |
讀/寫 |
0 |
0xFFFFF118 |
VICVectAddr7 |
向量地址7寄存器。 |
讀/寫 |
0 |
0xFFFFF11C |
VICVectAddr8 |
向量地址8寄存器。 |
讀/寫 |
0 |
0xFFFFF120 |
VICVectAddr9 |
向量地址9寄存器。 |
讀/寫 |
0 |
0xFFFFF124 |
VICVectAddr10 |
向量地址10寄存器。 |
讀/寫 |
0 |
0xFFFFF128 |
VICVectAddr11 |
向量地址11寄存器。 |
讀/寫 |
0 |
0xFFFFF12C |
VICVectAddr12 |
向量地址12寄存器。 |
讀/寫 |
0 |
0xFFFFF130 |
VICVectAddr13 |
向量地址13寄存器。 |
讀/寫 |
0 |
0xFFFFF134 |
VICVectAddr14 |
向量地址14寄存器。 |
讀/寫 |
0 |
0xFFFFF138 |
VICVectAddr15 |
向量地址15寄存器。 |
讀/寫 |
0 |
0xFFFFF13C |
VICVectAddr16 |
向量地址16寄存器。 |
讀/寫 |
0 |
0xFFFFF140 |
VICVectAddr17 |
向量地址17寄存器。 |
讀/寫 |
0 |
0xFFFFF144 |
VICVectAddr18 |
向量地址18寄存器。 |
讀/寫 |
0 |
0xFFFFF148 |
VICVectAddr19 |
向量地址19寄存器。 |
讀/寫 |
0 |
0xFFFFF14C |
VICVectAddr20 |
向量地址20寄存器。 |
讀/寫 |
0 |
0xFFFFF150 |
VICVectAddr21 |
向量地址21寄存器。 |
讀/寫 |
0 |
0xFFFFF154 |
VICVectAddr22 |
向量地址22寄存器。 |
讀/寫 |
0 |
0xFFFFF158 |
VICVectAddr23 |
向量地址23寄存器。 |
讀/寫 |
0 |
0xFFFFF15C |
VICVectAddr24 |
向量地址24寄存器。 |
讀/寫 |
0 |
0xFFFFF160 |
VICVectAddr25 |
向量地址25寄存器。 |
讀/寫 |
0 |
0xFFFFF164 |
VICVectAddr26 |
向量地址26寄存器。 |
讀/寫 |
0 |
0xFFFFF168 |
VICVectAddr27 |
向量地址27寄存器。 |
讀/寫 |
0 |
0xFFFFF16C |
VICVectAddr28 |
向量地址28寄存器。 |
讀/寫 |
0 |
0xFFFFF170 |
VICVectAddr29 |
向量地址29寄存器。 |
讀/寫 |
0 |
0xFFFFF174 |
VICVectAddr30 |
向量地址30寄存器。 |
讀/寫 |
0 |
0xFFFFF178 |
VICVectAddr31 |
向量地址31寄存器。 |
讀/寫 |
0 |
0xFFFFF17C |
VICVectPriority0 |
向量優先級0寄存器。該寄存器設置IRQ0的優先級。 |
讀/寫 |
0xF |
0xFFFFF200 |
VICVectPriority1 |
向量優先級1寄存器。 |
讀/寫 |
0xF |
0xFFFFF204 |
VICVectPriority2 |
向量優先級2寄存器。 |
讀/寫 |
0xF |
0xFFFFF208 |
VICVectPriority3 |
向量優先級3寄存器。 |
讀/寫 |
0xF |
0xFFFFF20C |
VICVectPriority4 |
向量優先級4寄存器。 |
讀/寫 |
0xF |
0xFFFFF210 |
VICVectPriority5 |
向量優先級5寄存器。 |
讀/寫 |
0xF |
0xFFFFF214 |
VICVectPriority6 |
向量優先級6寄存器。 |
讀/寫 |
0xF |
0xFFFFF218 |
VICVectPriority7 |
向量優先級7寄存器。 |
讀/寫 |
0xF |
0xFFFFF21C |
VICVectPriority8 |
向量優先級8寄存器。 |
讀/寫 |
0xF |
0xFFFFF220 |
VICVectPriority9 |
向量優先級9寄存器。 |
讀/寫 |
0xF |
0xFFFFF224 |
VICVectPriority10 |
向量優先級10寄存器。 |
讀/寫 |
0xF |
0xFFFFF228 |
VICVectPriority11 |
向量優先級11寄存器。 |
讀/寫 |
0xF |
0xFFFFF22C |
VICVectPriority12 |
向量優先級12寄存器。 |
讀/寫 |
0xF |
0xFFFFF230 |
VICVectPriority13 |
向量優先級13寄存器。 |
讀/寫 |
0xF |
0xFFFFF234 |
VICVectPriority14 |
向量優先級14寄存器。 |
讀/寫 |
0xF |
0xFFFFF238 |
VICVectPriority15 |
向量優先級15寄存器。 |
讀/寫 |
0xF |
0xFFFFF23C |
VICVectPriority16 |
向量優先級16寄存器。 |
讀/寫 |
0xF |
0xFFFFF240 |
VICVectPriority17 |
向量優先級17寄存器。 |
讀/寫 |
0xF |
0xFFFFF244 |
VICVectPriority18 |
向量優先級18寄存器。 |
讀/寫 |
0xF |
0xFFFFF248 |
VICVectPriority19 |
向量優先級19寄存器。 |
讀/寫 |
0xF |
0xFFFFF24C |
VICVectPriority20 |
向量優先級20寄存器。 |
讀/寫 |
0xF |
0xFFFFF250 |
VICVectPriority21 |
向量優先級21寄存器。 |
讀/寫 |
0xF |
0xFFFFF254 |
VICVectPriority22 |
向量優先級22寄存器。 |
讀/寫 |
0xF |
0xFFFFF258 |
VICVectPriority23 |
向量優先級23寄存器。 |
讀/寫 |
0xF |
0xFFFFF25C |
VICVectPriority24 |
向量優先級24寄存器。 |
讀/寫 |
0xF |
0xFFFFF260 |
VICVectPriority25 |
向量優先級25寄存器。 |
讀/寫 |
0xF |
0xFFFFF264 |
VICVectPriority26 |
向量優先級26寄存器。 |
讀/寫 |
0xF |
0xFFFFF268 |
VICVectPriority27 |
向量優先級27寄存器。 |
讀/寫 |
0xF |
0xFFFFF26C |
VICVectPriority28 |
向量優先級28寄存器。 |
讀/寫 |
0xF |
0xFFFFF270 |
VICVectPriority29 |
向量優先級29寄存器。 |
讀/寫 |
0xF |
0xFFFFF274 |
VICVectPriority30 |
向量優先級30寄存器。 |
讀/寫 |
0xF |
0xFFFFF278 |
VICVectPriority31 |
向量優先級31寄存器。 |
讀/寫 |
0xF |
0xFFFFF27C |
VICAddress |
向量地址寄存器。當發生IRQ中斷時,該寄存器保存當前有效中斷。 |
讀/寫 |
0 |
0xFFFFFF00 |
[1] 復位值只反映了使用位的數值,不包括保留位的內容。
下面將按照VIC邏輯中的使用順序對VIC寄存器進行描述,該順序爲從與中斷請求輸入最密切的寄存器開始,到由軟件所使用的最抽象的寄存器結束。對大多數人來講,這也是在學習VIC時讀取寄存器的最佳順序。
1、 軟件中斷寄存器VICSoftInt(0xFFFFF018)
軟件中斷寄存器用於產生軟件中斷。在執行任何邏輯操做以前,該寄存器的內容將與32個不一樣外設的中斷請求相「或」。
表4.41 軟件中斷寄存器位描述
位 |
值 |
功能描述 |
復位值 |
31:0 |
0 |
不產生中斷請求。寫0至該位無效。 |
0 |
1 |
強制產生與該位相關的中斷請求。 |
2、軟件中斷清零寄存器VICSoftIntClear(0xFFFFF01C)
軟件中斷清零寄存器爲只寫寄存器。對該寄存器一個或多個位寫1能夠清除軟件中斷寄存器中的置1位。
表4.42 軟件中斷清零寄存器
位 |
值 |
功能描述 |
復位值 |
31:0 |
0 |
寫0無效果。 |
0 |
1 |
寫1則軟件中斷寄存器中對應位被清除。 |
3、原始中斷狀態寄存器VICRawIntr(0xFFFFF008)
該只讀寄存器讀取全部32箇中斷請求和軟件中斷的狀態,無論中斷是否使能或分類。
表4.43 原始中斷狀態寄存器
位 |
值 |
功能描述 |
復位值 |
31:0 |
0 |
對應位的中斷請求或軟件中斷未聲明。 |
- |
1 |
對應位的中斷請求或軟件中斷聲明。 |
4、中斷使能寄存器VICIntEnable(0xFFFFF010)
中斷使能寄存器爲讀寫寄存器。該寄存器使能分配位FIQ和IRQ的中斷請求或軟件中斷。
表4.44 中斷使能寄存器
位 |
功能描述 |
復位值 |
31:0 |
當讀取該寄存器時,讀1表示中斷請求使能爲FIQ或IRQ,寫入1,使能中斷請求或軟件中斷分配爲FIQ或IRQ;寫入0無效。 |
0 |
5、中斷使能清零寄存器VICIntEnClr(0xFFFFF014)
該寄存器爲只寫寄存器。用於清除中斷使能寄存器中一個或多箇中斷使能位。
表4.45中斷使能清零寄存器
位 |
值 |
功能描述 |
復位值 |
31:0 |
0 |
寫0無效果。 |
- |
1 |
寫1則中斷使能寄存器中對應位被清除。 |
6、中斷選擇寄存器VICIntSelect(0xFFFFF00C)
該寄存器將32箇中斷請求分別分配爲FIQ或IRQ.
表4.46中斷選擇寄存器
位 |
值 |
功能描述 |
復位值 |
31:0 |
0 |
表示對應位的中斷請求類型爲IRQ。 |
0 |
1 |
表示對應位的中斷請求類型爲FIQ。 |
7、IRQ狀態寄存器VICIRQStatus(0xFFFFF000)
IRQ狀態寄存器爲只讀寄存器。該寄存器讀取使能並分配爲IRQ的中斷請求狀態。
表4.47 IRQ狀態寄存器
位 |
功能描述 |
復位值 |
31:0 |
某位讀取出1表明該位中斷請求使能且被分配爲IRQ。 |
0 |
8、FIQ狀態寄存器VICFIQStatus(0xFFFFF004)
FIQ狀態寄存器爲只讀寄存器。該寄存器讀取使能並分配爲FIQ的中斷請求狀態。若是有超過一個請求分配爲FIQ,FIQ服務程序可讀取該寄存器來肯定是哪個(幾個)請求被激活。
表4.48 FIQ狀態寄存器
位 |
功能描述 |
復位值 |
31:0 |
某位讀取出1表明該位中斷請求使能且被分配爲FIQ。 |
0 |
9、向量地址寄存器VICVectAddr0~31(0xFFFFF100~17C)
向量地址寄存器一共有32個,每一個寄存器可讀可寫。這些寄存器對應保存32個向量IRQ中斷的中斷服務程序的入口地址。
表4.49 向量地址寄存器
位 |
功能描述 |
復位值 |
31:0 |
每一個寄存器對應一箇中斷源,該寄存器保存該中斷源服務程序入口地址,中斷源見表4.54。 |
0x00000000 |
10、向量優先級寄存器VICVectPriority0~31(0xFFFFF200~27C)
向量優先級寄存器用於設置32個向量中斷各自優先級。優先級從0~15,0爲最高優先級,15最低。全部向量優先級寄存器復位值爲最低優先級15,且寄存器容許寫操做逐一更改32個向量中斷優先級。當優先級相同的中斷同時發生,向量地址寄存器VICVectAddr0~31數值小的優先被相應。
表4.50向量優先級寄存器
位 |
功能描述 |
復位值 |
3:0 |
設置相應向量中斷優先級0~15。 |
0xF |
31:4 |
保留位,用戶軟件不該對保留進行寫操做,讀出的保留位值未定義。 |
NA |
11、向量地址寄存器VICAddress(0xFFFFFF00)
當處理器響應一個IRQ中斷後,該中斷的中斷服務程序(ISR)地址能夠從向量地址寄存器VICAddress讀出。而這個地址是由VIC從32向量地址寄存器VICVectPriority0~31其中一個讀出裝入進來的。
表4.51向量地址寄存器
位 |
功能描述 |
復位值 |
31:0 |
包含當前有效中斷的ISR入口地址。該寄存器在ISR結束前必須被寫入一個數值(任何值),以此更新VIC優先級硬件邏輯,其餘時間對該寄存器寫可能引發錯誤產生。 |
0 |
12、軟件優先級屏蔽寄存器VICSWPrioriyMask(0xFFFFF024)
軟件優先級屏蔽寄存器包含了16箇中斷優先級的屏蔽碼。
表4.52軟件優先級屏蔽寄存器
位 |
值 |
功能描述 |
復位值 |
15:0 |
0 |
中斷優先級被屏蔽。 |
0xFFFF |
1 |
中斷優先級未被屏蔽。 |
||
31:16 |
- |
保留位,用戶軟件不該對保留進行寫操做,讀出的保留位值未定義。 |
NA |
13、保護使能寄存器VICProtection(0xFFFFF020)
保護使能寄存器爲可讀寫寄存器。該寄存器控制VIC寄存器是否能被用戶軟件在用戶態下訪問。且該寄存器自己只能在管態下訪問。
表4.53保護使能寄存器
位 |
值 |
功能描述 |
復位值 |
0 |
0 |
VIC寄存器能夠在用戶態或管態下訪問。 |
0 |
1 |
VIC寄存器只能在管態下訪問。 |
||
31:1 |
- |
保留位,用戶軟件不該對保留進行寫操做,讀出的保留位值未定義 |
NA |
表4.54列出了每一個外圍模塊的全部中斷源。每一個外圍設備都有一條或多條中斷線鏈接到向量中斷控制器,並且每根中斷線可能表明不止一種中斷源。除了肯定標準的ARM內核,中斷線自己沒有標誌或優先級。
表4.54 鏈接VIC通道的中斷源
功能模塊 |
標誌 |
VIC通道 |
屏蔽碼 |
WDT |
看門狗中斷(WDINT) |
0 |
0x0000 0001 |
- |
軟件中斷保留 |
1 |
0x0000 0002 |
ARM內核 |
調試器接收命令中斷 |
2 |
0x0000 0004 |
ARM內核 |
調試器發送命令中斷 |
3 |
0x0000 0008 |
定時器0 |
匹配0~1(MR0,MR1),捕獲0~1(CR0,CR1) |
4 |
0x0000 0010 |
功能模塊 |
標誌 |
VIC通道 |
屏蔽碼 |
定時器1 |
匹配0~2(MR0,MR1,MR2),捕獲0~1(CR0,CR1) |
5 |
0x0000 0020 |
UART0 |
Rx線狀態(RLS),發送保持寄存器空(THRE),Rx數據可用(RDA),字符超時指示(CTI) |
6 |
0x0000 0040 |
UART1 |
Rx線狀態(RLS),發送保持寄存器空(THRE),Rx數據可用(RDA),字符超時指示(CTI),Modem控制更改 |
7 |
0x0000 0080 |
PWM0, PWM1 |
PWM0匹配0~6,PWM0捕獲0,PWM1匹配0~6,PWM1捕獲0~1 |
8 |
0x0000 0100 |
I2C0 |
SI(狀態改變) |
9 |
0x0000 0200 |
SPI,SSP0 |
SPI中斷標誌(SPIF),模式錯誤(MODF),SSP0的Tx FIFO半空(TXRIS),SSP0的Rx FIFO 半滿(RXRIS),SSP0接收超時(RTRIS),SSP0接收溢出(RORRIS) |
10 |
0x0000 0400 |
SSP1 |
SSP1的Tx FIFO半空(TXRIS),SSP1的Rx FIFO 半滿(RXRIS),SSP1接收超時(RTRIS),SSP1接收溢出(RORRIS) |
11 |
0x0000 0800 |
PLL |
PLL鎖定 |
12 |
0x0000 1000 |
RTC |
計數器增長(RTCCIF),報警(RTCALF),Sub-second中斷(RTCSSF) |
13 |
0x0000 2000 |
系統控制 (外部中斷) |
外部中斷0(EINT0) |
14 |
0x0000 4000 |
外部中斷1(EINT1) |
15 |
0x0000 8000 |
|
外部中斷2(EINT2) |
16 |
0x0001 0000 |
|
外部中斷3(EINT3) 注:EINT3與GPIO中斷共享 |
17 |
0x0002 0000 |
|
ADC0 |
A/D轉換器0 |
18 |
0x0004 0000 |
I2C1 |
SI(狀態改變) |
19 |
0x0008 0000 |
BOD |
掉電檢測 |
20 |
0x0010 0000 |
以太網 |
Wakeup,軟件中斷,傳輸成功,傳輸結束,傳輸錯誤,傳輸XX,接收成功,接收結束,接受錯誤,接受溢出 |
21 |
0x0020 0000 |
USB |
USB_INT_REQ_LP,USB_INT_REQ_HP,USB_INT_REQ_DMA |
22 |
0x0040 0000 |
CAN |
CAN命令,CAN0傳輸,CAN0接收,CAN1傳輸,CAN1接收 |
23 |
0x0080 0000 |
SD/MMC接口 |
RxDataAvlbl ,TxDataAvlbl,RxFifoEmpty,TxFifoEmpty,RxFifoFull,TxFifoFull,RxFifoHalFull,TxFifoHalEmpty,RxActive,TxActive,CmdActive,DataBlockEnd,StartBitErr,DataEnd,CmdSent,CmdRespEnd,RxOverrun,TxUnderrun,DataTimeOut,CmdTimeOut,DataCrcFail,CmdCrcFail |
24 |
0x0100 0000 |
GP DMA |
DMA通道0狀態,DMA通道1狀態 |
25 |
0x0200 0000 |
定時器2 |
匹配0~3,捕獲0~1 |
26 |
0x0400 0000 |
定時器3 |
匹配0~3,捕獲0~1 |
27 |
0x0800 0000 |
UART2 |
Rx線狀態(RLS),發送保持寄存器空(THRE),Rx數據可用(RDA),字符超時指示(CTI) |
28 |
0x1000 0000 |
UART3 |
Rx線狀態(RLS),發送保持寄存器空(THRE),Rx數據可用(RDA),字符超時指示(CTI) |
29 |
0x2000 0000 |
I2C2 |
SI(狀態改變) |
30 |
0x4000 0000 |
I2S |
Irq_rx,Irq_tx |
31 |
0x8000 0000 |
1.VIC中斷與片內RAM調試。若是在片內RAM中調試程序(JTAG調試)時須要使用中斷,那麼必須將中斷向量從新映射到地址0x00000000,這樣作是由於全部的異常向量都位於地址0x00000000及以上。經過將寄存器MEMMAP(位於系統控制模塊當中)配置爲用戶RAM模式來實現這一點。另外,用戶代碼編譯連接時應該使中斷向量表裝載到地址0x40000000。
2.多個FIQ中斷。雖然能夠選擇多箇中斷源(經過設置VICIntSelect)爲FIQ中斷,可是隻有一個專門的中斷服務程序來響應全部出現的FIQ請求。所以,若是分配爲FIQ的中斷多於一個,FIQ中斷服務程序就必須先讀取VICFIQStatus的內容來識別具體有效的FIQ中斷源,而後在進行相應中斷處理。不過仍是建議用戶只設置一個FIQ中斷,以確保FIQ中斷延遲最小。
3.IRQ中斷服務程序與VIC寄存器。在中斷服務程序執行完畢後,對外設中斷標準的清零將會對VIC寄存器(VICRawIntr,VICFIQStatus和VICIRQStatus)當中的對應位產生影響。另外,爲了可以服務下次中斷,必須在中斷返回以前對VICVectAddr寄存器執行一次寫操做(通常可寫入0),該寫操做將清零內部中斷優先級硬件當中對應的標誌。
4.VIC中斷禁能操做。若要禁止VIC中斷,則必須清零VICIntEnable寄存器中的對應位,這能夠經過寫VICIntEnClr寄存器實現。這一樣應用於VICSoftInt和VICSoftIntClear。
本節以實現按鍵的外部中斷爲例介紹向量中斷控制器的使用,以及在IAR Embedded Workbench集成開發環境中編寫中斷服務程序的方法。
1、基本操做流程
設置IRQ/FIQ中斷,如果IRQ中斷,則能夠設置爲向量中斷並分配中斷優先級,而後設置中斷使能,以及向量中斷對應地址。當產生中斷後,如果IRQ中斷,則能夠讀取向量地址寄存器,而後跳轉到相應服務代碼。當退出中斷時,對向量地址寄存器寫0,通知VIC中斷結束。
對於中斷源(VIC通道)的IRQ/FIQ選擇,由VICIntSelect寄存器控制,每一箇中斷源於VICIntSelect的各位一一對應,好比VIC通道14(外部中斷0)與VICIntSelect的Bit14位對應,設置該位爲1,則分配爲FIQ中斷,不然爲IRQ中斷。
2、設置異常向量表
在LPC2400的啓動代碼中(在cstartup.s79文件中)首先設置異常向量表並設置各個模式下的堆棧指針,最後跳轉到用戶程序運行。異常向量表是一個包含8種異常狀況的向量表,具體分配如表4.55所示。
表4.55 ARM異常向量表
地址 |
異常類型 |
0x0000 0000 |
復位 |
0x0000 0004 |
未定義指令 |
0x0000 0008 |
軟件中斷 |
0x0000 000C |
預取指令錯誤 |
0x0000 0010 |
取數據錯誤 |
0x0000 0014 |
保留 |
0x0000 0018 |
IRQ中斷 |
0x0000 001C |
FIQ中斷 |
系統一旦產生IRQ中斷,LPC2400處理器會切換到IRQ模式,而且跳轉到向量表0x00000018地址執行程序。如程序清單4.6②所示,在IRQ向量處使用的指令與其餘向量不一樣,當CPU執行這條指令但尚未跳轉時, [PC, # -0x0120]表示當前PC值減去0x0120 ,當前PC的值爲0x00000020,減去0x0120爲0xFFFFFF00。這是VIC特殊寄存器VICVectAddr的物理地址,該寄存器保存當前將要服務的IRQ中斷服務程序的入口,因此用這條LDR指令就能夠直接跳轉到須要的中斷服務程序中。
一旦產生FIQ中斷,處理器會切換到FIQ模式,而且跳轉到向量表0x0000001C地址執行程序。如程序清單4.6③所示,程序將跳到FIQ_Handler標號處,處理FIQ中斷服務程序。
代碼清單4.6 異常向量表設置
__program_start
LDR PC, =Reset_Handler ①
LDR PC, =Undef_Handler
LDR PC, =SWI_Handler
LDR PC, =PAbt_Handler
LDR PC, =DAbt_Handler
B .
LDR PC, [PC, # -0x0120] ②
LDR PC, =FIQ_Handler ③
3、VIC初始化
接下來,在LPC2400的啓動代碼中包含有VIC初始化程序,如代碼清單4.7所列。程序首先禁止全部中斷(代碼清單4.7 ①),設置VICVectAddr寄存器的值爲0,將全部中斷設置爲IRQ中斷(代碼清單4.7 ③)。最後在for循環中把全部向量地址寄存器內容設置爲0(代碼清單4.7 ④ ),向量優先級寄存器設置爲0xF,最低中斷優先級(代碼清單4.7 ⑤)。
禁止全部中斷是避免調試時一箇中斷沒有響應就再次裝入程序運行,而VIC狀態錯誤不能正確識別中斷。
代碼清單4.7 init_VIC()——VIC初始化
VICIntEnClr = 0xffffffff; ①
VICVectAddr = 0; ②
VICIntSelect = 0; ③
/* set all the vector and vector control register to 0 */
for ( i = 0; i < VIC_SIZE; i++ ) // 32箇中斷服務向量復位
{
vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4);
vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4);
*vect_addr = 0x0; //中斷服務函數都指向開頭 ④
*vect_cntl = 0xF; //優先級最低 ⑤
}
4、編寫中斷服務程序
IAR Embedded Workbench C/C++編譯器支持ARM核的IRQ中斷、FIQ快速中斷和SWI軟件中斷,能夠直接採用C語言編寫中斷函數。中斷函數必須採用ARM模式編譯,若是用戶正在使用的是Thumb模式,應採用擴展關鍵字__arm或「#pragma type_attribute=__arm」指令將其轉換到ARM模式。IRQ中斷函數採用擴展字__irq或#pragma type_attribute=__irq」指令聲明,如程序清單4.8 ①所示。FIQ中斷函數採用擴展字__fiq或#pragma type_attribute=__fiq」指令聲明。須要特別注意的是,IRQ和FIQ函數的返回值類型必須爲void,而且不能帶有參數。
在中斷服務程序開始先清除外部中斷標誌寄存器EXTINT中EINT0位,以後進行中斷服務處理,最後寫VICVectAddr寄存器,更新VIC優先級邏輯,以相應下次外部中斷。
代碼清單4.8 EINT0_Handler()——外部中斷服務函數
__irq __arm void EINT0_Handler (void) ①
{
EXTINT = EINT0; /* 清除EXTINT寄存器中EINT0位 */ ②
……/*中斷服務*/
VICVectAddr = 0; /* 寫VICVectAddr寄存器,更新VIC優先級邏輯 */ ③
}
5、安裝外部中斷服務程序
安裝外部中斷服務程序主要是初始化VIC的幾個特別寄存器。Install_irq一共有3個參數:IntNumber爲鏈接VIC的中斷通道數,HandlerAddr爲中斷函數地址,Priority爲該中斷通道的優先級。
如代碼清單4.9所示,函數首先設置中斷使能清除寄存器VICIntEnClr的對應位,無效該中斷。接着經過中斷通道數IntNumber獲得對應向量地址寄存器VICVectAddrX和向量優先級寄存器VICVectPriorityX地址。而後使用其他兩個參數初始化這兩個寄存器。最後置位中斷使能寄存器VICIntEnable的對應,位使能該中斷。
代碼清單4.9 install_irq()——中斷安裝函數
DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
{
DWORD *vect_addr;
DWORD *vect_cntl;
VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */
vect_addr=(DWORD *)(VIC_BASE_ADDR+VECT_ADDR_INDEX+IntNumber*4);
vect_cntl=(DWORD *)(VIC_BASE_ADDR+VECT_CNTL_INDEX+IntNumber*4);
*vect_addr=(DWORD)HandlerAddr; /* set interrupt vector */
*vect_cntl=Priority;
VICIntEnable = 1 << IntNumber; /* Enable Interrupt */
}
代碼清單4.10爲調用install_irq函數安裝EINT0_Handler中斷服務函數的方法。
代碼清單4.10安裝EINT0_Handler函數
if ( install_irq( EINT0_INT, (void *)EINT0_Handler, HIGHEST_PRIORITY ) = = FALSE )
{
return (FALSE);
}
在嵌入式系統硬件開發過程當中,直接設計和開發目標板硬件會有至關大的難度和風險,能夠先經過設計最小系統,將所需IO引腳都引出到一個插針或者闆闆鏈接器(FPC)上。實際應用電路板(本文簡稱底板)另行設計,最小系統板能夠同直插封裝的器件同樣與應用電路板想鏈接。下文將介紹LPC2400的最小系統。
現在如同LPC2400這樣的MCU芯片將FLASH、SRAM以及一些總線等集成在一片芯片中,可是仍離不開一些外圍電路的設計。這部分外圍電路主要爲MCU提供電源、時鐘震盪、電壓轉換、I/O口保護和驅動等功能。LPC2400的最小系統如圖4.15所示,這個最小系統此文暫稱爲核心板。
圖4.15. LPC2400核心板
本核心板分爲供電電路、時鐘電路、復位電路以及外部存儲器電路。現作簡單介紹:
1.供電電路。核心板電源主要靠實際應用電路+3.3V提供,經過左右兩排插針中的相關引腳提供。LPC2400芯片採用單電源(+3.3V)供電,這樣能夠簡化電路設計,下降產品成本。電源紋波直接影響着整個電路的工做,爲了獲得穩定的電壓,須要外接一些電容。這些電容分爲兩類,一類爲儲能電容,這些電容的電容值比較大,如1uF、10uF等。另外一類爲去耦電容,其電容值較小,如0.1uF、0.01uF等,它們能夠達到抑制高頻噪聲的功用。
2.時鐘電路。這部分電路主要有晶體振盪器、電容以及電阻組成。目前有些MCU已經將該部分集成到芯片內部,可是可能是以RC振盪電路形式提供所需時鐘,其穩定性得不到較高的保證。使用外部晶振能夠使MCU獲得穩定的時鐘頻率。
3.復位電路。雖然目前大部分的MCU都集成有上電覆位電路,在系統上電時MCU會自動產生復位信號。但在設計初期能夠加入手動復位電路以方便調試。外部復位電路能夠採用阻容振盪電路,也可採用諸如MAX811或者SGM811之類的專用復位芯片。
4.外部存儲器電路。目前中高檔的MCU尤爲是ARM內核的MCU都引出有外部總線。因爲大中型軟件系統對FLASH以及RAM的容量的需求以及內部集成FLASH形成成本偏高的現實,使得采用外部FLASH做爲存儲器件最爲合適。
因爲LPC2478與LPC2470、LPC2468以及LPC2460等恩智浦LPC2400系列ARM7單片機在引腳上是兼容的,因此LPC2400最小系統一樣也適用於上述芯片。
如圖4.15所示,左右兩排插針引出了實際應用電路板上所需的功能引腳,上下兩排焊盤引出了LPC2478所能提供的外部總線。
LPC2400最小系統包括一下幾個部分:電源電路、時鐘電路、復位電路、JTAG調試電路以及功能接口電路等。其中各個部分功能以下:
一、 時鐘電路給MCU提供一個外部12MHz的以及一個32.768MHz的石英振盪器。
二、 復位電路是經過引腳的方式與底板上的手動復位相連。經過底板復位電路提供手動復位信號。
三、 JTAG電路可讓用戶方便的經過仿真器調試或者下載程序。
四、 外部存儲電路,即有板載外部存儲器(如Nor Flash、Nand Flash和SDRAM),又將外部總線引出方便用戶經過外部總線擴展其餘器件。
根據電路板的工做環境,可能會對電路板提出不一樣的要求。諸如噪聲以及干擾較強的場合,以及對系統穩定性、可靠性要求較高時,印刷電路板會採用多層板設計。通常地,6層板噪聲比4層板低10dB,4層板比雙面板的噪聲低20dB。但板層越多,相應的成本也就越高。如圖4.15所示的核心板採用6層板設計,爲測試提供了穩定可靠的電路。
4.1 簡單說明LPC2400系列芯片復位時的處理流程。
4.2 LPC2400系列芯片的存儲器空間是如何分佈的?
4.3 LPC2400芯片的引腳一般都是複用的,當要使用引腳的某個功能時,應如何進行設置?
4.4 簡述使能PLL的工做過程。
4.5 若是LPC2400使用的外部晶振頻率爲12MHz,計算最大的系統時鐘頻率CCLK爲多少,此時M值和N值各爲多少,並編寫設置PLL的程序段。
4.6 LPC2400有哪些下降功耗的措施?
4.7 若是要使用外部中斷0來喚醒掉電的LPC2400,應設置哪些寄存器,各寄存器的值應爲多少?寫出其程序段。
3.1 ARM 處理器的指令格式
ARM內核屬於RISC結構,因此其指令集有着一些獨特的特色:指令長度固定,指令格式的種類少,尋址方式簡單。因爲ARM處理器採用固定長度的32位指令,所以處理器內部硬件設計可以被簡化。ARM處理器內部的指令譯碼採用硬佈線邏輯,不使用微程序控制,以減小指令的譯碼時間,大部分指令能夠在一個時鐘週期內完成。
ARM處理器的指令按功能可分爲七大類:加載/存儲指令、數據處理指令、乘法指令、跳轉指令、程序狀態寄存器處理指令、協處理器指令和異常中斷指令。
須要特別指出的是,ARM處理器的指令集是加載/存儲型的,也即指令集僅能處理寄存器中的數據,並且處理結果都要放回寄存器中,而對系統存儲器的訪問則須要經過專門的加載/存儲指令來完成。
按照操做數的特色分,ARM指令能夠分爲無操做數指令、單操做數指令、雙操做數指令和三操做數指令。每條指令都由操做碼域、條件碼域、條件碼設置域、目標操做數、第一操做數寄存器和第二操做數組成。
每條ARM指令都是32位的,其格式以下:
31 28 27 25 24 21 20 19 16 15 12 11 0
條件碼 |
類別碼 |
操做碼 |
S |
目的寄存器 |
第一操做數 |
第二操做數 |
用ARM指令助記符表示爲:
<opcode> {<cond>} {S} <Rd>, <Rn>, <shift_op2>
每一個域的含義以下:
1) <opcode>:操做碼域,指令編碼的助記符;
2) {<cond>}:條件碼域,指令容許執行的條件編碼。花括號表示此項可缺省。
ARM指令的一個重要特色是能夠條件執行,每條ARM指令的條件碼域包含4位條件碼,共16種。幾乎全部指令均根據CPSR中條件碼的狀態和指令條件碼域的設置有條件的執行。當指令執行條件知足時,指令被執行,不然被忽略。指令條件碼及其助記符後綴表示參見表3.1。
每種條件碼可用兩個字符表示,這兩個字符能夠做爲後綴添加在指令助記符的後面和指令同時使用。例如,跳轉指令B能夠加上後綴EQ變爲BEQ,表示「相等則跳轉」,即當CPSR中的Z標誌置位時發生跳轉。
表3.1 指令的條件碼
條件碼 |
助記符後綴 |
標 志 |
含 義 |
0000 |
EQ |
Z置位 |
相等 |
0001 |
NE |
Z清零 |
不相等 |
0010 |
CS |
C置位 |
無符號數大於或等於 |
0011 |
CC |
C清零 |
無符號數小於 |
0100 |
MI |
N置位 |
負數 |
0101 |
PL |
N清零 |
正數或零 |
0110 |
VS |
V置位 |
溢出 |
0111 |
VC |
V清零 |
未溢出 |
1000 |
HI |
C置位Z清零 |
無符號數大於 |
1001 |
LS |
C清零Z置位 |
無符號數小於或等於 |
1010 |
GE |
N等於V |
帶符號數大於或等於 |
1011 |
LT |
N不等於V |
帶符號數小於 |
1100 |
GT |
Z清零且(N等於V) |
帶符號數大於 |
1101 |
LE |
Z置位或(N不等於V) |
帶符號數小於或等於 |
1110 |
AL |
忽略 |
無條件執行 |
3) {S}:條件碼設置域。這是一個可選項,當在指令中設置{S}域時,指令執行的結果將會影響程序狀態寄存器CPSR中相應的狀態標誌。
例如:
ADD R0,R1,R2; R1與R2的和存放到R0寄存器中,不影響狀態寄存器
ADDS R0,R1,R2; 執行加法的同時影響狀態寄存器
指令中比較特殊的是CMP指令,它不須要加S後綴就默認地根據計算結構更改程序狀態寄存器。
4) <Rd>:目的操做數。ARM指令中的目的操做數老是一個寄存器。若是<Rd>與第一操做數寄存器<Rn>相同,也必需要指明,不能缺省。
5) <Rn>:第一操做數。ARM指令中的第一操做數也必須是個寄存器。
6) <shift_op2>:第二操做數。在第二操做數中能夠是寄存器、內存存儲單元或者當即數。
因爲第二操做數只有12個bit,用第二操做數表示當即數時,其取值範圍爲0~212-1,要表示超出這個範圍的當即數,一般要依靠僞指令實現。
所謂尋址方式就是處理器根據指令中給出的地址信息來尋找物理地址的方式。目前ARM指令系統支持以下幾種常見的尋址方式。
當即尋址也叫當即數尋址,這是一種特殊的尋址方式,操做數自己就在指令中給出,只要取出指令也就取到了操做數。這個操做數被稱爲當即數,對應的尋址方式也就叫作當即尋址。例如如下指令:
ADD R0,R0,#1 ;R0←R0+1
ADD R0,R0,#0x3f ;R0←R0+0x3f
在以上兩條指令中,第二操做數即爲當即數,要求以「#」爲前綴,對於以十六進制表示的當即數,還要求在「#」後加上「0x」,以二進制表示的當即數,要求在「#」後加上「%」。
噹噹即數大於第二操做數的表示範圍時,一般用如下僞指令實現:
LDR R0,=#0xffff0000
寄存器尋址就是利用寄存器中的數值做爲操做數,這種尋址方式是各種微處理器常常採用的一種方式,也是一種執行效率較高的尋址方式。如下指令:
ADD R0,R1,R2 ;R0←R1+R2
該指令的執行效果是將寄存器R1和R2的內容相加,其結果存放在寄存器R0中。
寄存器間接尋址就是以寄存器中的值做爲操做數的地址,而操做數自己存放在存儲器中。例如如下指令:
ADD R0,R1,[R2] ;R0←R1+[R2]
LDR R0,[R1] ;R0←[R1]
STR R0,[R1] ;[R1]←R0
在第一條指令中,以寄存器R2的值做爲操做數的地址,在存儲器中取得一個操做數後與R1相加,結果存入寄存器R0中。
第二條指令將以R1的值爲地址的存儲器中的數據傳送到R0中。
第三條指令將R0的值傳送到以R1的值爲地址的存儲器中。
基址變址尋址就是將寄存器(該寄存器通常稱做基址寄存器)的內容與指令中給出的地址偏移量相加,從而獲得一個操做數的有效地址。變址尋址方式經常使用於訪問某基地址附近的地址單元。採用變址尋址方式的指令常見有如下幾種形式,以下所示:
LDR R0,[R1,#4] ;R0←[R1+4]
LDR R0,[R1,#4]! ;R0←[R1+4]、R1←R1+4
LDR R0,[R1] ,#4 ;R0←[R1]、R1←R1+4
LDR R0,[R1,R2] ;R0←[R1+R2]
在第一條指令中,將寄存器R1的內容加上4造成操做數的有效地址,從而取得操做數存入寄存器R0中。
在第二條指令中,將寄存器R1的內容加上4造成操做數的有效地址,從而取得操做數存入寄存器R0中,而後,R1的內容自增4個字節。
在第三條指令中,以寄存器R1的內容做爲操做數的有效地址,從而取得操做數存入寄存器R0中,而後,R1的內容自增4個字節。
在第四條指令中,將寄存器R1的內容加上寄存器R2的內容造成操做數的有效地址,從而取得操做數存入寄存器R0中。
多寄存器尋址是ARM處理器特有的一種尋址方式。因爲ARM內核有較多的通用寄存器,採用多寄存器尋址方式,一條指令能夠一次完成多個寄存器值的傳送。這種尋址方式能夠用一條指令完成傳送最多16個通用寄存器的值。例如如下指令:
LDMIA R0,{R1,R2,R3,R4} ;R1←[R0]
;R2←[R0+4]
;R3←[R0+8]
;R4←[R0+12]
該指令的後綴IA表示在每次執行完加載/存儲操做後,R0按字長度增長,所以,指令可將連續存儲單元的值傳送到R1~R4。
多個連續的寄存器能夠用「-」符號鏈接;不連續的寄存器用「,」分隔書寫,如上例可寫成:
LDMIA R0,{R1-R4}
LDMIA R0,{R1-R3,R4}
寄存器移位尋址是ARM指令集特有的尋址方式。ARM處理器內嵌桶型移位器(Barrel Shifter),支持數據的各類移位操做。當第二操做數爲寄存器時,能夠加入移位操做選項對它進行各類移位操做。
移位操做包括以下6種類型:
一、LSL(或ASL)邏輯(算術)左移
尋址格式:
通用寄存器,LSL(或ASL) 操做數
完成對通用寄存器中的內容進行邏輯(或算術)的左移操做,按操做數所指定的數量向左移位,低位用零來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, LSL#2 ;將R1中的內容左移兩位後傳送到R0中。
二、LSR邏輯右移
尋址格式:
通用寄存器,LSR 操做數
完成對通用寄存器中的內容進行右移的操做,按操做數所指定的數量向右移位,左端用零來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, LSR#2 ;將R1中的內容右移兩位後傳送到R0中,左端用零來填充。
三、ASR算術右移
尋址格式:
通用寄存器,ASR 操做數
完成對通用寄存器中的內容進行右移的操做,按操做數所指定的數量向右移位,左端用第31位的值來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, ASR#2 ;將R1中的內容右移兩位後傳送到R0中,左端用第31位的值來填充。
四、ROR循環右移
尋址格式:
通用寄存器,ROR 操做數
完成對通用寄存器中的內容進行循環右移的操做,按操做數所指定的數量向右循環移位,左端用右端移出的位來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。顯然,當進行32位的循環右移操做時,通用寄存器中的值不改變。
如:
MOV R0, R1, ROR#2 ;將R1中的內容循環右移兩位後傳送到R0中。
五、RRX帶擴展的循環右移
尋址格式:
通用寄存器,RRX 操做數
完成對通用寄存器中的內容進行帶擴展的循環右移的操做,按操做數所指定的數量向右循環移位,左端用進位標誌位C來填充。其中,操做數能夠是通用寄存器,也能夠是當即數(0~31)。
如:
MOV R0, R1, RRX#2 ;將R1中的內容進行帶擴展的循環右移兩位後傳送到R0中。
與基址變址尋址方式相相似,相對尋址以程序計數器PC的當前值爲基地址,指令中的地址標號做爲偏移量,將二者相加以後獲得操做數的有效地址。如下程序段完成子程序的調用和返回,跳轉指令BL採用了相對尋址方式:
BL NEXT ;跳轉到子程序NEXT處執行
……
NEXT
……
MOV PC,LR ;從子程序返回
堆棧是一種數據結構,按先進後出(First In Last Out,FILO)的方式工做,使用一個稱做堆棧指針的專用寄存器指示當前的操做位置,堆棧指針老是指向棧頂。
當堆棧指針指向最後壓入堆棧的數據時,稱爲滿堆棧(Full Stack),而當堆棧指針指向下一個將要放入數據的空位置時,稱爲空堆棧(Empty Stack)。
同時,根據堆棧的生成方式,又能夠分爲遞增堆棧(Ascending Stack)和遞減堆棧(Decending Stack)。當堆棧由低地址向高地址生成時,稱爲遞增堆棧,當堆棧由高地址向低地址生成時,稱爲遞減堆棧。這樣就有四種類型的堆棧工做方式,ARM微處理器支持這四種類型的堆棧工做方式,即:
1. 滿遞增堆棧(FA):堆棧指針指向最後壓入的數據,且由低地址向高地址生成。
2. 滿遞減堆棧(FD):堆棧指針指向最後壓入的數據,且由高地址向低地址生成。
3. 空遞增堆棧(EA):堆棧指針指向下一個將要放入數據的空位置,且由低地址向高地址生成。
4. 空遞減堆棧(ED):堆棧指針指向下一個將要放入數據的空位置,且由高地址向低地址生成。
本節對ARM指令集的七大類指令進行詳細的描述。
ARM處理器支持加載/存儲指令用於在寄存器和存儲器之間傳送數據,加載指令用於將存儲器中的數據傳送到寄存器,存儲指令則完成相反的操做。經常使用的加載存儲指令以下:
一、LDR指令
LDR指令的格式爲:
LDR{條件} 目的寄存器,<存儲器地址>
LDR指令用於從存儲器中將一個32位的字數據傳送到目的寄存器中。該指令一般用於從存儲器中讀取32位的字數據到通用寄存器,而後對數據進行處理。當程序計數器PC做爲目的寄存器時,指令從存儲器中讀取的字數據被看成目的地址,從而能夠實現程序流程的跳轉。該指令在程序設計中比較經常使用,且尋址方式靈活多樣,請讀者認真掌握。
如:
LDR R0,[R1] ;將存儲器地址爲R1的字數據讀入寄存器R0。
LDR R0,[R1,R2] ;將存儲器地址爲R1+R2的字數據讀入寄存器R0。
LDR R0,[R1,#8] ;將存儲器地址爲R1+8的字數據讀入寄存器R0。
LDR R0,[R1,R2] ! ;將存儲器地址爲R1+R2的字數據讀入寄存器R0,並將
;新地址R1+R2寫入R1。
LDR R0,[R1,#8] ! ;將存儲器地址爲R1+8的字數據讀入寄存器R0,並將新
;地址R1+8寫入R1。
LDR R0,[R1],R2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地
;址R1+R2寫入R1。
LDR R0,[R1,R2,LSL#2]! ;將存儲器地址爲R1+R2×4的字數據讀入寄存器R0,
;並將新地址R1+R2×4寫入R1。
LDR R0,[R1],R2,LSL#2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地
;址R1+R2×4寫入R1。
二、STR指令
STR指令的格式爲:
STR{條件} 源寄存器,<存儲器地址>
STR指令用於從源寄存器中將一個32位的字數據傳送到存儲器中。該指令在程序設計中比較經常使用,且尋址方式靈活多樣,使用方式可參考指令LDR。
如:
STR R0,[R1],#8 ;將R0中的字數據寫入以R1爲地址的存儲器中,並將新地址R1+8寫入R1。
STR R0,[R1,#8] ;將R0中的字數據寫入以R1+8爲地址的存儲器中。
LDR/STR指令均可以加B、H、SB、SH的後綴,分別表示加載/存儲字節、半字、帶符號的字節、帶符號的半字。如LDRB指令表示從存儲器加載一個字節進寄存器。當使用這些後綴時,要注意所使用的存儲器要支持訪問的數據寬度。
三、LDM(或STM)批量數據加載/存儲指令
LDM(或STM)指令的格式爲:
LDM(或STM){條件}{類型} 基址寄存器{!},寄存器列表{∧}
LDM(或STM)指令用於從由基址寄存器所指示的一片連續存儲器到寄存器列表所指示的多個寄存器之間傳送數據,該指令的常見用途是將多個寄存器的內容入棧或出棧。其中,{類型}爲如下幾種狀況:
IA 每次傳送後地址加1;
IB 每次傳送前地址加1;
DA 每次傳送後地址減1;
DB 每次傳送前地址減1;
FD 滿遞減堆棧;
ED 空遞減堆棧;
FA 滿遞增堆棧;
EA 空遞增堆棧;
{!}爲可選後綴,若選用該後綴,則當數據傳送完畢以後,將最後的地址寫入基址寄存器,不然基址寄存器的內容不改變。
基址寄存器不容許爲R15,寄存器列表能夠爲R0~R15的任意組合。
{∧}爲可選後綴,當指令爲LDM且寄存器列表中包含R15,選用該後綴時表示:除了正常的數據傳送以外,還將SPSR複製到CPSR。同時,該後綴還表示傳入或傳出的是用戶模式下的寄存器,而不是當前模式下的寄存器。
如:
STMFD R13!,{R0,R4-R12,LR} ;將寄存器列表中的寄存器(R0,R4到R12,LR)存入堆棧。
LDMFD R13!,{R0,R4-R12,PC} ;將堆棧內容恢復到寄存器(R0,R4到R12,LR)。
四、SWP數據交換指令
SWP指令的格式爲:
SWP{條件} 目的寄存器,源寄存器1,[源寄存器2]
SWP指令用於將源寄存器2所指向的存儲器中的字數據傳送到目的寄存器中,同時將源寄存器1中的字數據傳送到源寄存器2所指向的存儲器中。顯然,當源寄存器1和目的寄存器爲同一個寄存器時,指令交換該寄存器和存儲器的內容。
如:
SWP R0,R1,[R2] ;將R2所指向的存儲器中的字數據傳送到R0,同時將R1中的字數據傳送到R2所指向的存儲單元。
SWP R0,R0,[R1] ;該指令完成將R1所指向的存儲器中的字數據與R0中的字數據交換。
數據處理指令可分爲數據傳送指令、算術邏輯運算指令和比較指令等。
數據傳送指令用於在寄存器和存儲器之間進行數據的雙向傳輸。
算術邏輯運算指令完成經常使用的算術與邏輯的運算,該類指令不但將運算結果保存在目的寄存器中,同時更新CPSR中的相應條件標誌位。
比較指令不保存運算結果,只更新CPSR中相應的條件標誌位。
一、 MOV指令
MOV指令的格式爲:
MOV{條件}{S} 目的寄存器,源操做數
MOV指令可完成從另外一個寄存器、被移位的寄存器或將一個當即數加載到目的寄存器。其中S選項決定指令的操做是否影響CPSR中條件標誌位的值,當沒有S時指令不更新CPSR中條件標誌位的值。
如:
MOV R1,R0 ;將寄存器R0的值傳送到寄存器R1
MOV PC,R14 ;將寄存器R14的值傳送到PC,經常使用於子程序返回
MOV R1,R0,LSL#3 ;將寄存器R0的值左移3位後傳送到R1
二、 MVN指令
MVN指令的格式爲:
MVN{條件}{S} 目的寄存器,源操做數
MVN指令可完成從另外一個寄存器、被移位的寄存器、或將一個當即數加載到目的寄存器。與MOV指令不一樣之處是在傳送以前按位被取反了,即把一個被取反的值傳送到目的寄存器中。其中S決定指令的操做是否影響CPSR中條件標誌位的值,當沒有S時指令不更新CPSR中條件標誌位的值。
如:
MVN R0,#0 ;將當即數0取反傳送到寄存器R0中,完成後R0=-1
三、 CMP指令
CMP指令的格式爲:
CMP{條件} 操做數1,操做數2
CMP指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數進行比較,同時更新CPSR中條件標誌位的值。該指令進行一次減法運算,但不存儲結果,只更改條件標誌位。標誌位表示的是操做數1與操做數2的關係(大、小、相等),例如,當操做數1大於操做操做數2,則此後的有GT 後綴的指令將能夠執行。
如:
CMP R1,R0 ;將寄存器R1的值與寄存器R0的值相減,並根據結果設置CPSR的標誌位
CMP R1,#100 ;將寄存器R1的值與當即數100相減,並根據結果設置CPSR的標誌位
四、 CMN指令
CMN指令的格式爲:
CMN{條件} 操做數1,操做數2
CMN指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數取反後進行比較,同時更新CPSR中條件標誌位的值。該指令實際完成操做數1和操做數2相加,並根據結果更改條件標誌位。
如:
CMN R1,R0 ;將寄存器R1的值與寄存器R0的值相加,並根據結果設置CPSR的標誌位
CMN R1,#100 ;將寄存器R1的值與當即數100相加,並根據結果設置CPSR的標誌位
五、 TST指令
TST指令的格式爲:
TST{條件} 操做數1,操做數2
TST指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數進行按位的與運算,並根據運算結果更新CPSR中條件標誌位的值。操做數1是要測試的數據,而操做數2是一個位掩碼,該指令通常用來檢測是否設置了特定的位。
如:
TST R1,#%1 ;用於測試在寄存器R1中是否設置了最低位(%表示二進制數)
TST R1,#0xffe ;將寄存器R1的值與當即數0xffe按位與,並根據結果設置CPSR的標誌位
六、 TEQ指令
TEQ指令的格式爲:
TEQ{條件} 操做數1,操做數2
TEQ指令用於把一個寄存器的內容和另外一個寄存器的內容或當即數進行按位的異或運算,並根據運算結果更新CPSR中條件標誌位的值。該指令一般用於比較操做數1和操做數2是否相等。
如:
TEQ R1,R2 ;將寄存器R1的值與寄存器R2的值按位異或,並根據結果設置CPSR的標誌位
七、 ADD指令
ADD指令的格式爲:
ADD{條件}{S} 目的寄存器,操做數1,操做數2
ADD指令用於把兩個操做數相加,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。
如:
ADD R0,R1,R2 ; R0 = R1 + R2
ADD R0,R1,#256 ; R0 = R1 + 256
ADD R0,R2,R3,LSL#1 ; R0 = R2 + (R3 << 1)
八、 ADC指令
ADC指令的格式爲:
ADC{條件}{S} 目的寄存器,操做數1,操做數2
ADC指令用於把兩個操做數相加,再加上CPSR中的C條件標誌位的值,並將結果存放到目的寄存器中。它使用一個進位標誌位,這樣就能夠作比32位大的數的加法,注意不要忘記設置S後綴來更改進位標誌。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。
如下指令序列完成兩個128位數的加法,第一個數由高到低存放在寄存器R7~R4,第二個數由高到低存放在寄存器R11~R8,運算結果由高到低存放在寄存器R3~R0:
ADDS R0,R4,R8 ; 加低端的字
ADCS R1,R5,R9 ; 加第二個字,帶進位
ADCS R2,R6,R10 ; 加第三個字,帶進位
ADC R3,R7,R11 ; 加第四個字,帶進位
九、 SUB指令
SUB指令的格式爲:
SUB{條件}{S} 目的寄存器,操做數1,操做數2
SUB指令用於把操做數1減去操做數2,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令可用於有符號數或無符號數的減法運算。
如:
SUB R0,R1,R2 ; R0 = R1 - R2
SUB R0,R1,#256 ; R0 = R1 - 256
SUB R0,R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)
十、SBC指令
SBC指令的格式爲:
SBC{條件}{S} 目的寄存器,操做數1,操做數2
SBC指令用於把操做數1減去操做數2,再減去CPSR中的C條件標誌位的反碼,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令使用進位標誌來表示借位,這樣就能夠作大於32位的減法,注意不要忘記設置S後綴來更改進位標誌。該指令可用於有符號數或無符號數的減法運算。
如:
SUBS R0,R1,R2 ; R0 = R1 - R2 - !C,並根據結果設置CPSR的進位標誌位
11、RSB指令
RSB指令的格式爲:
RSB{條件}{S} 目的寄存器,操做數1,操做數2
RSB指令稱爲逆向減法指令,用於把操做數2減去操做數1,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令可用於有符號數或無符號數的減法運算。
如:
RSB R0,R1,R2 ; R0 = R2 – R1
RSB R0,R1,#256 ; R0 = 256 – R1
RSB R0,R2,R3,LSL#1 ; R0 = (R3 << 1) - R2
十二、RSC指令
RSC指令的格式爲:
RSC{條件}{S} 目的寄存器,操做數1,操做數2
RSC指令用於把操做數2減去操做數1,再減去CPSR中的C條件標誌位的反碼,並將結果存放到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令使用進位標誌來表示借位,這樣就能夠作大於32位的減法,注意不要忘記設置S後綴來更改進位標誌。該指令可用於有符號數或無符號數的減法運算。
如:
RSC R0,R1,R2 ; R0 = R2 – R1 - !C
1三、AND指令
AND指令的格式爲:
AND{條件}{S} 目的寄存器,操做數1,操做數2
AND指令用於在兩個操做數上進行邏輯與運算,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令經常使用於屏蔽操做數1的某些位。
如:
AND R0,R0,#3 ; 該指令保持R0的0、1位,其他位清零。
1四、ORR指令
ORR指令的格式爲:
ORR{條件}{S} 目的寄存器,操做數1,操做數2
ORR指令用於在兩個操做數上進行邏輯或運算,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令經常使用於設置操做數1的某些位。
如:
ORR R0,R0,#3 ; 該指令設置R0的0、1位,其他位保持不變。
1五、EOR指令
EOR指令的格式爲:
EOR{條件}{S} 目的寄存器,操做數1,操做數2
EOR指令用於在兩個操做數上進行邏輯異或運算,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。該指令經常使用於反轉操做數1的某些位。
如:
EOR R0,R0,#3 ; 該指令反轉R0的0、1位,其他位保持不變。
1六、BIC指令
BIC指令的格式爲:
BIC{條件}{S} 目的寄存器,操做數1,操做數2
BIC指令用於清除操做數1的某些位,並把結果放置到目的寄存器中。操做數1應是一個寄存器,操做數2能夠是一個寄存器,被移位的寄存器,或一個當即數。操做數2爲32位的掩碼,若是在掩碼中設置了某一位,則清除這一位。未設置的掩碼位保持不變。
如:
BIC R0,R0,#%1011 ; 該指令清除 R0 中的位 0、1、和 3,其他的位保持不變。
ARM微處理器支持的乘法指令與乘加指令共有6條,可分爲運算結果爲32位和運算結果爲64位兩類。與前面的數據處理指令不一樣,指令中的所有操做數、目的寄存器必須爲通用寄存器,不能對操做數使用當即數或被移位的寄存器,同時,目的寄存器和操做數1必須是不一樣的寄存器。
一、 MUL指令
MUL指令的格式爲:
MUL{條件}{S} 目的寄存器,操做數1,操做數2
MUL指令完成將操做數1與操做數2的乘法運算,並把結果放置到目的寄存器中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數或無符號數。
如:
MUL R0,R1,R2 ;R0 = R1 × R2
MULS R0,R1,R2 ;R0 = R1 × R2,同時設置CPSR中的相關條件標誌位
二、 MLA指令
MLA指令的格式爲:
MLA{條件}{S} 目的寄存器,操做數1,操做數2,操做數3
MLA指令完成將操做數1與操做數2的乘法運算,再將乘積加上操做數3,並把結果放置到目的寄存器中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數或無符號數。
如:
MLA R0,R1,R2,R3 ;R0 = R1 × R2 + R3
MLAS R0,R1,R2,R3 ;R0 = R1 × R2 + R3,同時設置CPSR中的相關條件標誌位
三、 SMULL指令
SMULL指令的格式爲:
SMULL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
SMULL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位放置到目的寄存器Low中,結果的高32位放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數。
如:
SMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
四、 SMLAL指令
SMLAL指令的格式爲:
SMLAL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
SMLAL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位同目的寄存器Low中的值相加後又放置到目的寄存器Low中,結果的高32位同目的寄存器High中的值相加後又放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的有符號數。
對於目的寄存器Low,在指令執行前存放64位加數的低32位,指令執行後存放結果的低32位。
對於目的寄存器High,在指令執行前存放64位加數的高32位,指令執行後存放結果的高32位。
如:
SMLAL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1
五、 UMULL指令
UMULL指令的格式爲:
UMULL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
UMULL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位放置到目的寄存器Low中,結果的高32位放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的無符號數。
如:
UMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
六、 UMLAL指令
UMLAL指令的格式爲:
UMLAL{條件}{S} 目的寄存器Low,目的寄存器低High,操做數1,操做數2
UMLAL指令完成將操做數1與操做數2的乘法運算,並把結果的低32位同目的寄存器Low中的值相加後又放置到目的寄存器Low中,結果的高32位同目的寄存器High中的值相加後又放置到目的寄存器High中,同時能夠根據運算結果設置CPSR中相應的條件標誌位。其中,操做數1和操做數2均爲32位的無符號數。
對於目的寄存器Low,在指令執行前存放64位加數的低32位,指令執行後存放結果的低32位。
對於目的寄存器High,在指令執行前存放64位加數的高32位,指令執行後存放結果的高32位。
如:
UMLAL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1
跳轉指令用於實現程序流程的跳轉,在ARM程序中有兩種方法能夠實現程序流程的跳轉:使用專門的跳轉指令、直接向程序計數器PC寫入跳轉地址值。
直接向PC寫入跳轉地址值,能夠實如今4GB的地址空間中任意跳轉,在跳轉以前結合使用MOV LR,PC等相似指令,能夠保存未來的返回地址值,從而實如今4GB連續的線性地址空間的子程序調用。
使用跳轉指令能夠完成從當前指令向前或向後的32MB的地址空間的跳轉。
一、 B指令
B指令的格式爲:
B{條件} 目標地址
B指令是最簡單的跳轉指令。一旦遇到一個 B 指令,ARM 處理器將當即跳轉到給定的目標地址,從那裏繼續執行。注意存儲在跳轉指令中的實際值是相對當前PC值的一個偏移量,而不是一個絕對地址,它的值由彙編器來計算(參考尋址方式中的相對尋址)。它是 24 位有符號數,左移兩位後有符號擴展爲 32 位,表示的有效偏移爲 26 位(先後32MB的地址空間)。
如:
B Label ;程序無條件跳轉到標號Label處執行
CMP R1,#0 ;當CPSR寄存器中的Z條件碼置位時,程序跳轉到標號Label處執行
BEQ Label
二、 BL指令
BL指令的格式爲:
BL{條件} 目標地址
BL 是另外一個跳轉指令,但跳轉以前,會在寄存器R14中保存PC的當前內容,所以,能夠經過將R14 的內容從新加載到PC中,來返回到跳轉指令以後的那個指令處執行。該指令是實現子程序調用的一個基本但經常使用的手段。
如:
BL Label ;當程序無條件跳轉到標號Label處執行時,同時將當前的PC值保存到R14中
Label標號處能夠是一個子程序,在子程序的最後能夠使用MOV PC,LR指令跳回BL Label指令處的下一條指令繼續執行。
三、 BLX指令
BLX指令的格式爲:
BLX 目標地址
BLX指令從ARM指令集跳轉到指令中所指定的目標地址,並將處理器的工做狀態由ARM狀態切換到Thumb狀態,該指令同時將PC的當前內容保存到寄存器R14中。所以,當子程序使用Thumb指令集,而調用者使用ARM指令集時,能夠經過BLX指令實現子程序的調用和處理器工做狀態的切換。同時,子程序的返回能夠經過將寄存器R14值複製到PC中來完成。
四、 BX指令
BX指令的格式爲:
BX{條件} 目標地址
BX指令跳轉到指令中所指定的目標地址,目標地址處的指令既能夠是ARM指令,也能夠是Thumb指令。
ARM指令不容許直接操做程序狀態寄存器CPSR和SPSR。能夠經過程序狀態寄存器訪問指令,在程序狀態寄存器和通用寄存器之間傳送數據,而後在通用寄存器中進行處理。
一、 MRS指令
MRS指令的格式爲:
MRS{條件} 通用寄存器,程序狀態寄存器(CPSR或SPSR)
MRS指令用於將程序狀態寄存器的內容傳送到通用寄存器中。該指令通常用在如下幾種狀況:
1) 當須要改變程序狀態寄存器的內容時,可用MRS將程序狀態寄存器的內容讀入通用寄存器,修改後再寫回程序狀態寄存器。
2) 當在異常處理或進程切換時,須要保存程序狀態寄存器的值,可先用該指令讀出程序狀態寄存器的值,而後保存。
如:
MRS R0,CPSR ;傳送CPSR的內容到R0
MRS R0,SPSR ;傳送SPSR的內容到R0
二、 MSR指令
MSR指令的格式爲:
MSR{條件} 程序狀態寄存器(CPSR或SPSR)_<域>,操做數
MSR指令用於將操做數的內容傳送到程序狀態寄存器的特定域中。其中,操做數能夠爲通用寄存器或當即數。<域>用於設置程序狀態寄存器中須要操做的位,32位的程序狀態寄存器可分爲4個域:
位[31:24]爲條件標誌位域,用f表示;
位[23:16]爲狀態位域,用s表示;
位[15:8]爲擴展位域,用x表示;
位[7:0]爲控制位域,用c表示;
該指令一般用於恢復或改變程序狀態寄存器的內容,在使用時,通常要在MSR指令中指明將要操做的域。
如:
MSR CPSR,R0 ;傳送R0的內容到CPSR
MSR SPSR,R0 ;傳送R0的內容到SPSR
MSR CPSR_c,R0 ;傳送R0的內容到SPSR,但僅僅修改CPSR中的控制位域
ARM微處理器可支持多達16個協處理器,用於各類協處理操做,在程序執行的過程當中,每一個協處理器只執行鍼對自身的協處理指令,忽略ARM處理器和其餘協處理器的指令。
ARM的協處理器指令主要用於ARM處理器初始化ARM協處理器的數據處理操做,以及在ARM處理器的寄存器和協處理器的寄存器之間傳送數據,和在ARM協處理器的寄存器和存儲器之間傳送數據。
一、CDP指令
CDP指令的格式爲:
CDP{條件} 協處理器編碼,協處理器操做碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操做碼2。
CDP指令用於ARM處理器通知ARM協處理器執行特定的操做,若協處理器不能成功完成特定的操做,則產生未定義指令異常。其中協處理器操做碼1和協處理器操做碼2爲協處理器將要執行的操做,目的寄存器和源寄存器均爲協處理器的寄存器,指令不涉及ARM處理器的寄存器和存儲器。
如:
CDP P3,2,C12,C10,C3,4 ;該指令完成協處理器P3的初始化
二、LDC指令
LDC指令的格式爲:
LDC{條件}{L} 協處理器編碼,目的寄存器,[源寄存器]
LDC指令用於將源寄存器所指向的存儲器中的字數據傳送到目的寄存器中,若協處理器不能成功完成傳送操做,則產生未定義指令異常。其中,{L}選項表示指令爲長讀取操做,如用於雙精度數據的傳輸。
如:
LDC P3,C4,[R0] ;將ARM處理器的寄存器R0所指向的存儲器中的字數據傳送到協處理器P3的寄存器C4中。
三、STC指令
STC指令的格式爲:
STC{條件}{L} 協處理器編碼,源寄存器,[目的寄存器]
STC指令用於將源寄存器中的字數據傳送到目的寄存器所指向的存儲器中,若協處理器不能成功完成傳送操做,則產生未定義指令異常。其中,{L}選項表示指令爲長讀取操做,如用於雙精度數據的傳輸。
如:
STC P3,C4,[R0] ;將協處理器P3的寄存器C4中的字數據傳送到ARM處理器的寄存器R0所指向的存儲器中。
四、MCR指令
MCR指令的格式爲:
MCR{條件} 協處理器編碼,協處理器操做碼1,源寄存器,目的寄存器1,目的寄存器2,協處理器操做碼2。
MCR指令用於將ARM處理器寄存器中的數據傳送到協處理器寄存器中,若協處理器不能成功完成操做,則產生未定義指令異常。其中協處理器操做碼1和協處理器操做碼2爲協處理器將要執行的操做,源寄存器爲ARM處理器的寄存器,目的寄存器1和目的寄存器2均爲協處理器的寄存器。
如:
MCR P3,3,R0,C4,C5,6 ;該指令將ARM處理器寄存器R0中的數據傳送到協處理器P3的寄存器C4和C5中。
五、MRC指令
MRC指令的格式爲:
MRC{條件} 協處理器編碼,協處理器操做碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操做碼2。
MRC指令用於將協處理器寄存器中的數據傳送到ARM處理器寄存器中,若協處理器不能成功完成操做,則產生未定義指令異常。其中協處理器操做碼1和協處理器操做碼2爲協處理器將要執行的操做,目的寄存器爲ARM處理器的寄存器,源寄存器1和源寄存器2均爲協處理器的寄存器。
如:
MRC P3,3,R0,C4,C5,6 ;該指令將協處理器P3的寄存器中的數據傳送到ARM處理器寄存器中。
一、SWI指令
SWI指令的格式爲:
SWI{條件} 24位的當即數
SWI指令用於產生軟件中斷,以便用戶程序能調用操做系統的系統例程。操做系統在SWI的異常處理程序中提供相應的系統服務,指令中24位的當即數指定用戶程序調用系統例程的類型,相關參數經過通用寄存器傳遞,當指令中24位的當即數被忽略時,用戶程序調用系統例程的類型由通用寄存器R0的內容決定,同時,參數經過其餘通用寄存器傳遞。
如:
SWI 0x02 ;該指令調用操做系統編號位02的系統例程。
二、BKPT指令
BKPT指令的格式爲:
BKPT 16位的當即數
BKPT指令產生軟件斷點中斷,可用於程序的調試。
爲兼容數據總線寬度爲16位的應用系統,ARM體系結構除了支持執行效率很高的32位ARM指令集之外,同時支持16位的Thumb指令集。Thumb指令集是ARM指令集的一個子集,容許指令編碼爲16位的長度。與等價的32位代碼相比較,Thumb指令集在保留32位代碼優點的同時,大大的節省了系統的存儲空間。
全部的Thumb指令都有對應的ARM指令,並且Thumb的編程模型也對應於ARM的編程模型,在應用程序的編寫過程當中,只要遵循必定調用的規則,Thumb子程序和ARM子程序就能夠互相調用。當處理器在執行ARM程序段時,稱ARM處理器處於ARM工做狀態,當處理器在執行Thumb程序段時,稱ARM處理器處於Thumb工做狀態。
與ARM指令集相比較,Thumb指令集中的數據處理指令的操做數仍然是32位,指令地址也爲32位,但Thumb指令集爲實現16位的指令長度,捨棄了ARM指令集的一些特性,如大多數的Thumb指令是無條件執行的,而幾乎全部的ARM指令都是有條件執行的;大多數的Thumb數據處理指令的目的寄存器與其中一個源寄存器相同。
因爲Thumb指令的長度爲16位,即只用ARM指令一半的位數來實現一樣的功能,因此,要實現特定的程序功能,所需的Thumb指令的條數較ARM指令多。在通常的狀況下,Thumb指令與ARM指令的時間效率和空間效率關係爲:
— Thumb代碼所需的存儲空間約爲ARM代碼的60%~70%
— Thumb代碼使用的指令數比ARM代碼多約30%~40%
— 若使用32位的存儲器,ARM代碼比Thumb代碼快約40%
— 若使用16位的存儲器,Thumb代碼比ARM代碼快約40%~50%
— 與ARM代碼相比較,使用Thumb代碼,存儲器的功耗會下降約30%
顯然,ARM指令集和Thumb指令集各有其優勢,若對系統的性能有較高要求,應使用32位的存儲系統和ARM指令集,若對系統的成本及功耗有較高要求,則應使用16位的存儲系統和Thumb指令集。固然,若二者結合使用,充分發揮其各自的優勢,會取得更好的效果。
ARM編譯器通常都支持彙編語言的程序設計和C/C++語言的程序設計,以及二者的混合編程。在ARM彙編語言程序裏,有一些特殊指令助記符,這些助記符與指令系統的助記符不一樣,沒有相對應的操做碼,一般稱這些特殊指令助記符爲僞指令,他們所完成的操做稱爲僞操做。僞指令在源程序中的做用是爲完成彙編程序做各類準備工做的,這些僞指令僅在彙編過程當中起做用,一旦彙編結束,僞指令的使命就完成。
在ARM的彙編程序中,有以下幾種僞指令:ARM僞指令、符號定義僞指令、數據定義僞指令、段定義僞指令、模塊控制僞指令、彙編控制僞指令、宏處理僞指令等等。
須要特別指出的是,除了幾條ARM僞指令之外,其它的僞指令依賴於編譯器。也就是說,不一樣的ARM編譯器的僞指令集是不相同的。例如,ADS編譯器的段定義僞指令爲AREA,而IAR編譯器的段定義僞指令爲RSEG和ASEG。這種狀況使得不一樣編譯器下編出的ARM彙編程序是不一樣的。讀者在閱讀不一樣學習材料時應注意分辨在不一樣編譯器下ARM彙編程序的區別。
本書介紹的是IAR EWARM編譯器支持的ARM彙編僞指令。
ARM僞指令不是ARM指令集中的指令。它能夠象其它ARM指令同樣使用,但在編譯時這些指令將被等效的ARM指令所取代。
一、LDR-大範圍地址讀取
LDR僞指令的格式爲:
LDR{條件} reg,=expr/label_expr
reg爲加載的目的寄存器;expr爲32位當即數;label_expr爲地址表達式或外部表達式。
LDR僞指令將32位常量或一個32位地址加載到指定寄存器。
如:
LDR R0,=#0x12345 ;加載32位當即數0x12345到寄存器R0
LDR R0,=DATA_BUF+60 ;加載DATA_BUF地址+60
二、ADR-小範圍地址讀取
ADR僞指令的格式爲:
ADR{條件} reg,expr
reg爲加載的目的寄存器;expr爲相對偏移表達式,非字對齊時取值範圍爲-255~255字節,字對齊時取值範圍爲-1020~1020字節。
ADR僞指令將基於當前PC相對偏移的地址值讀取到寄存器中。
如:
Start: MOV R0,#10
ADR R4,start ;至關於SUB R4,PC,#0x0c
三、ADRL-中範圍地址讀取
ADRL僞指令與ADR相似,不一樣在expr的取值範圍,非字對齊時取值範圍爲64KB,字對齊時取值範圍爲256KB。
四、NOP-空操做
一、DCB和DC8
該僞指令的格式爲:
標號 DCB或DC8 表達式
DCB和DC8僞指令用於分配一片連續的8位字節存儲單元,並用僞指令中指定的表達式初始化。其中表達式能夠爲0~255的數字或字符串。
如:
Str DCB 「This is a test!」 ;分配一個字符串,每一個字符8位字節
二、DCW和DC1六、DCD和DC32
與DCB和DC8用法相同,不一樣的是分別分配16位半字節單元和32位字單元。
三、DF32和DF64
分別表示32位的單精度浮點數和64位的雙精度浮點數。
四、DS八、DS1六、DS24和DS32
分別用於保留8位字節、16位半字、24位字和32位字的存儲器空間。
如:
Dataspace DS8 100 ;保留100個8位字節的存儲器空間
一、=、ALIAS和EQU
該僞指令的格式爲:
標號 = 表達式
標號 ALIAS 表達式
標號 EQU 表達式
僞指令EQU和=可用於爲程序模塊中的常量、標號等賦值,定義的局部符號僅在其所在的模塊內有效。僞指令ALIAS爲符號起個別名。定義的符號採用PUBLIC僞指令聲明其屬性可以使之被其它模塊引用,引用其它模塊內符號時必須採用EXTERN僞指令聲明其屬性。
如:
Test EQU 50 ;定義符號Test的值爲50
二、ASSIGN、SET、SETA和VAR
用法與EQU等相似,可用於定義一個變量符號。採用VAR定義的變量符號不能用PUBLIC聲明其屬性。
三、DEFINE
用於定義在整個程序文件內都有效的全局符號。該符號能夠被文件內的全部程序模塊引用,但不能在同一文件內從新定義。
四、LIMIT
該僞指令的格式爲:
LIMIT 表達式, 最小值, 最大值, 提示信息
用於檢查表達式的值是否位於給定範圍以內。若是表達式值的範圍超限,則輸出提示信息。
如:
Speed VAR 23 ;定義符號speed的值爲23
LIMIT speed,10,30,…speed out of range… ;檢查speed的值是否超限
五、EXTERN(或IMPORT)
該僞指令的格式爲:
EXTERN 符號,[符號]……
EXTERN僞指令用於通知彙編器,要使用的符號在其它源文件中定義,但要在當前源文件中引用。
如:
Name Start ;程序模塊Start
EXTERN Main ;告訴彙編器Main符號在其它源文件中定義
……
BL Main ;在本模塊中引用Main符號
END
六、PUBLIC(或EXPORT)
該僞指令的格式爲:
PUBLIC 符號,[符號]……
PUBLIC僞指令用於在程序中聲明一個全局符號,該符號可在其它文件中引用。
七、REQUIRE
PUBLIC僞指令用於將一個符號標記爲已經被引用。
一、ASEG和ASEGN
該僞指令的格式爲:
ASEG [起始地址[(對齊)]]
ASEGN 段名[:存儲器類型],地址
ASEG僞指令用於定義一個絕對段,並設置段的起始地址。不指定地址值時第一個段默認起始地址爲0,後續段地址依次遞增。ASEGN僞指令用於設置指定段的絕對起始地址,並容許規定段類型。存儲器類型能夠爲CODE(代碼段)、DATA(數據段)、STACK(堆棧段)。
如:
ASEG 0 ;定義一個絕對段,起始地址0
ASEGN CODE:CODE,0 ;定義一個名爲CODE的代碼段,起始地址0
二、RSEG
該僞指令的格式爲:
RSEG 段名[:存儲器類型][:(NO)ROOT|(NO)REORDER|SORT][(對齊)]
RSEG僞指令用於定義一個可重定位段,段的起始地址由彙編器臨時分配。單個模塊中最多可定義65536個可重定位段。
如:
RSEG CODE:CODE:ROOT(2) ;定義一個名爲CODE的可重定位代碼段,用戶權限爲ROOT(可讀寫),段內存儲器對齊方式爲4字節對齊
三、DATA
該僞指令的格式爲:
DATA 段名[:存儲器類型][(對齊)]
DATA僞指令能夠在代碼段內定義一個數據區。
如:
RSEG CODE:CODE:ROOT(2)
DATA
f1: DC32 subrtn
四、STACK
該僞指令的格式爲:
COMMON 段名[:存儲器類型][(對齊)]
STACK僞指令用於定義一個堆棧段,用做堆棧的存儲器地址從高向低變化,而用做可重定位段的存儲器地址是從低向高變化。
五、COMMON
該僞指令的格式爲:
COMMON 段名[:存儲器類型][(對齊)]
COMMON僞指令用於定義公共段,各源文件中同名的COMMON段共享同一段內存。它的典型應用是多個不一樣子程序共享一段數據存儲區。中斷向量表也可安排在COMMON段,以便容許從多個服務子程序訪問。
六、CODE16和CODE32
CODE16僞指令用於告訴彙編器,其後的指令序列爲16位的Thumb指令;CODE32僞指令用於告訴彙編器,其後的指令序列爲32位的ARM指令。所以,在使用ARM指令和Thumb指令混合編程的代碼中,可用這兩條僞指令進行切換。但須要注意的是,它們只通知彙編器其後指令的類型,並不能對處理器進行狀態切換。
七、ORG
該僞指令的格式爲:
ORG 地址表達式
ORG僞指令用於設置段的起始地址。地址表達式的計算結果應與當前段的類型保持一致,如在RSEG(可重定位段)中,不要使用「ORG 10」,由於10是一個絕對地址,而應當使用「ORG .+10」,表示當前段偏移量爲10的地址。另外,地址表達式中不能包括任何前向和外部引用。
八、ALIGNRAM和ALIGNROM
該僞指令的格式爲:
ALIGNRAM 對齊
ALIGNROM 對齊[,填充值]
用於設置存儲器地址邊界的對齊方式,「對齊」是一個值爲2~30的常數,並按22~30設定對齊地址。ALIGNRAM以數據增量方式對齊,ALIGNROM以填充0字節方式對齊。
九、EVEN和ODD
該僞指令的格式爲:
EVEN [填充值]
ODD [填充值]
EVEN僞指令用於將程序計數器PC以偶數地址對齊(等價於ALIGNROM 1),ODD僞指令用於將程序計數器PC以奇數地址對齊。
一、NAME和PROGRAM
該僞指令的格式爲:
NAME 模塊名
PROGRAM 模塊名
NAME和PROGRAM僞指令用於定義一個程序模塊。程序模塊相似於C語言中的函數,是程序中相對獨立的一個部分。程序模塊即便沒有被調用也會被無條件連接。
如:
NAME Main ;定義一個名爲Main的程序模塊
二、END和ENDMOD
END僞指令用於結束整個彙編語言程序,ENDMOD用於結束當前程序模塊。每一個彙編語言程序最後必須使用END僞指令通知彙編器已經到了源程序結尾,以結束彙編。
三、LIBRARY和MODULE
該僞指令用於定義多模塊文件中的小模塊,其中每一個小模塊表明一段子程序,從而能夠方便地建立庫模塊文件。與NAME和PROGRAM不一樣的是,用LIBRARY和MODULE定義的模塊只有在被調用時纔會複製到連接代碼中。
四、RTMODEL
該僞指令的格式爲:
RTMODEL 關鍵字字符串,值字符串
該僞指令用於聲明模塊的運行模式屬性,以強制模塊之間的一致性。全部能被連接在一塊兒的模塊必須具備相同的關鍵字;值字符串要麼具備相同的值,要麼其值爲星號「*」。
一、$和INCLUDE
該僞指令的格式爲:
$ 文件名
INCLUDE 文件名
該僞指令用於給當前源文件加載頭文件。
二、CASEOFF和CASEON
該僞指令用於源程序文件中禁止和容許大小寫字符敏感。
三、LTORG
在使用ARM僞指令LDR加載地址數據時,要在適當的位置加入LTORG聲明一個數據區,把要加載的數據保存在數據區內,再用LDR讀出數據。LTORG僞指令一般放在無條件分支或子程序返回指令後面,這樣處理器就不會錯誤的將數據區中的數據看成指令執行。
四、RADIX
該僞指令用於聲明當前使用的數制形式。如:
RADIX 16D ;聲明當前使用十六進制數
MOV R0,#12 ;此處#12爲0x12
五、IF、ELSE和ENDIF
該僞指令的格式爲:
IF 邏輯表達式
指令序列1
ELSE
指令序列2
ENDIF
條件彙編僞指令能根據設定條件的成立與否決定是否對指令序列進行彙編生成目標代碼。若邏輯表達式爲真,則對指令序列1彙編生成目標代碼;不然對指令序列2彙編。其中還能夠用ELSEIF僞指令設定新條件。
如:
DEFINE Test ;定義一個全局變量Test
……
IF Test = TRUE
指令序列1
ELSE
指令序列2
ENDIF
一、MACRO和ENDM
該僞指令的格式爲:
宏名 MACRO [,參數][ ,參數]……
指令序列
ENDM
MACRO僞指令用於定義一個宏,引用宏時必須使用定義的宏名,並可向宏中傳遞參數。ENDM僞指令用於結束宏定義。
如:
errmac MACRO text
BL abort
DATA
DC8 text,0
ENDM
包含在MACRO和ENDM之間的指令序列稱爲宏定義體。在宏定義體的第一行應聲明宏的原型(包括宏名和所需的參數),而後就能夠在彙編程序中經過宏名來調用該指令序列。在源程序被編譯時,彙編器將宏調用展開,用宏定義中的指令序列代替程序中的宏調用,並將實際參數值傳遞給宏定義中的形式參數。
二、REPT和ENDR
該僞指令的格式爲:
REPT 表達式
指令序列
ENDR
該僞指令用於指示彙編器將指定的指令序列進行重複彙編,重複次數由表達式的值肯定。若是表達式的值爲0,則不進行任何操做。
三、REPTC和ENDR
該僞指令的格式爲:
REPTC 符號,替換字符串
指令序列
ENDR
該僞指令用於在宏展開時用替換字符串中的單個字符逐次替換符號。
四、REPTI和ENDR
該僞指令的格式爲:
REPTI 符號,替換字符串[,替換字符串]……
指令序列
ENDR
該僞指令用於在宏展開時用整個替換字符串替換符號。
ARM(Thumb)彙編語言的語句格式爲:
[標號[:]] 指令或僞指令 操做數 [;註釋]
其中,方括號內的內容爲可選項。
標號頂格書寫時後面可不用冒號,非頂格書寫時後面必須用冒號。
標號前加一個問號「?」前綴,表示該標號爲外部標號,且僅能經過彙編語言訪問;標號前加兩個下劃線「__」前綴,表示該標號爲外部標號,能經過C語言和彙編語言訪問;沒有前綴的標號爲局部標號,僅能在本模塊內訪問。
IAR彙編器對大小寫字符敏感,通常指令和僞指令助記符使用大寫,標號使用大小寫混雜的方式以示區分。
同時,若是一條語句太長,可將該長語句分爲若干行來書寫,在行的末尾用「\」表示下一行與本行爲同一條語句。
IAR彙編器規定彙編語言程序文件的默認擴展名爲「.s79」,也能夠用「.s」或「.asm」做爲擴展名。
在彙編語言程序設計中,常用各類符號代替地址、變量和常量等,以增長程序的可讀性。儘管符號的命名由編程者決定,但並非任意的,必須遵循如下的約定:
1.符號由大小寫字母、數字及下劃線組成,符號不能用數字開頭。
2.符號區分大小寫,同名的大、小寫符號會被編譯器認爲是兩個不一樣的符號。
3.符號在其做用範圍內必須惟一。
4.自定義的符號名不能與系統的保留字相同。
5.符號名不該與指令或僞指令同名。
6. IAR彙編器內部預約義符號以雙下劃線開頭和結尾。如:__IAR_SYSTEMS_ASM__。
一、 常量
程序中的常量是指其值在程序的運行過程當中不能被改變的量。ARM(Thumb)彙編程序所支持的常量有數字常量、邏輯常量和字符串常量。
數字常量通常爲32位的整數,看成爲無符號數時,其取值範圍爲0~232-1,看成爲有符號數時,其取值範圍爲-231~231-1。數字常量有4種表示形式:十進制數如123、-456等;十六進制數如0x123、0FFFFH等;八進制數如1234q等;二進制數如1010b等。
邏輯常量只有兩種取值狀況:TRUE和FALSE。
字符串常量爲一個固定的字符串,通常用於程序運行時的信息提示。用法與標準C語言相同。
二、 變量
程序中的變量是指其值在程序的運行過程當中能夠改變的量。ARM(Thumb)彙編程序所支持的變量有數字變量、邏輯變量和字符串變量。
數字變量用於在程序的運行中保存數字值,但注意數字值的大小不該超出數字變量所能表示的範圍。
邏輯變量用於在程序的運行中保存邏輯值,邏輯值只有兩種取值狀況:真或假。
字符串變量用於在程序的運行中保存一個字符串,但注意字符串的長度不該超出字符串變量所能表示的範圍。
在ARM(Thumb)彙編語言程序中,以程序段爲單位組織代碼。段是相對獨立的指令或數據序列,具備特定的名稱。段能夠分爲代碼段和數據段,代碼段的內容爲執行代碼,數據段存放代碼運行時須要用到的數據。一個彙編程序至少應該有一個代碼段,當程序較長時,能夠分割爲多個代碼段和數據段,多個段在程序編譯連接時最終造成一個可執行的映象文件。
可執行映象文件一般由如下幾部分構成:
1. 1個或多個代碼段,代碼段的屬性爲只讀。
2. 0個或多個包含初始化數據的數據段,數據段的屬性爲可讀寫。
3. 0個或多個不包含初始化數據的數據段,數據段的屬性爲可讀寫。
連接器根據系統默認或用戶設定的規則,將各個段安排在存儲器中的相應位置。所以源程序中段之間的相對位置與可執行的映象文件中段的相對位置通常不會相同。
如下是一個彙編語言源程序的基本結構:
代碼清單3.1
NAME ASM_EXAMPL ;定義一個名爲ARM_EXAMPL的程序模塊
RSEG CODE:CODE:ROOT(2) ;定義一個可重定位的代碼段
CODE32 ;執行32位ARM指令
ORG 0x1000 ;定義程序起始地址爲0x1000
Start: LDR R0,=0x3FF5000 ;Start處的地址即爲0x1000
LDR R1,=0xff
STR R1,[R0]
MOV R0,#0x10
MOV R1,#0x20
ADD R0,R0,R1
Stop: B Stop ;跳轉到指令自己,程序中止運行
ENDMOD ;本程序模塊結束
END ;本程序結束
程序很簡單,它完成的功能並不重要,但它已經表示出了一個ARM彙編語言程序的基本結構。
程序設計中的三種基本結構是:順序結構、分支結構和循環結構。在C語言中能夠使用if-else語句實現單分支和雙分支結構,也能夠經過switch-case語句實現多分支結構。可是在彙編語言中,分支結構通常是經過跳轉指令結合標號來實現的。
在ARM彙編語言程序中,因爲ARM指令支持條件執行,從而大大減小了分支程序的複雜程度。
例如:用兩個整數展轉相減的方法求它們的最大公約數。注意體會B指令加條件碼的執行方式。程序中使用的main標號是由於IAR彙編器通常默認從main標號處開始執行。
代碼清單3.2
NAME GCD
PUBLIC main ;聲明外部引用標號main
B main ;從main標號處開始執行
RSEG CODE:CODE
CODE32
main: MOV R0,#120
MOV R1,#96
Gcd: CMP R0,R1 ;比較兩數的大小
BEQ Stop ;若是兩數相等則跳到結束處
BLT Less ;若是R0<R1則跳到Less標號處
SUB R0,R0,R1 ;不然R0=R0-R1
B Gcd
Less: SUB R1,R1,R0 ;R1=R1-R0
B Gcd
Stop: B Stop ;跳轉到指令自己,程序中止運行
ENDMOD ;本程序模塊結束
END ;本程序結束
經過跳轉指令還能夠實現程序的循環結構。
例如:求n=1+2+…+10累加的和。
代碼清單3.3
NAME SUM
PUBLIC main
B main
RSEG CODE
CODE32
main: MOV R0,#10
MOV R1,R0 ;利用R1寄存器作循環計數器
Loop: SUBS R1,R1,1 ;循環次數減1
ADD R0,R0,R1
BNE Loop ;循環次數爲0則結束循環
Stop: B Stop
ENDMOD
END
經過BL指令能夠實現子程序調用,語法:BL子程序名。
在子程序的結束處,能夠經過MOV PC,LR返回到主程序中。一般能夠使用寄存器R0~R3完成傳遞參數到子程序和從子程序返回運算的結果。
如下是使用BL指令調用子程序的彙編語言源程序的例子,該程序編寫了一個在內存裏拷貝字符串的子程序,而後在主程序裏調用它。
代碼清單3.4
NAME STRCPY
PUBLIC main
B main
RSEG CODE
CODE32
main: LDR R1,=srcstr ;R1指向源字符串
LDR R0,=dststr ;R0指向目標字符串
BL strcopy ;調用strcopy子程序
stop: B stop ;程序中止
strcopy: ;子程序定義
LDRB R2,[R1],#1 ;讀一個字符到R2,並更新源字符地址
STRB R2,[R0],#1 ;寫一個字符,並更新目的字符地址
CMP R2,#0 ;是否結束。以數字0爲標誌
BNE strcopy ;循環執行
DATA ;數據區
srcstr DCB "First string - source ",0
dststr DCB "Second string - destination ",0
ENDMOD
END
查表法是編程中經常使用的一種技巧。當程序涉及到較多的數據、數據串或數據表格時,能夠經過地址來對它們進行訪問。一般有兩種方法裝載地址:(1)經過ADR和ADRL僞指令直接裝載地址;(2)經過僞指令LDR Rd,=Label從數據表格中裝載地址。
下面的程序設置了3個參數,arithfunc根據3個參數返回一個R0值。當R0=0時,R0=R1+R2;當R0=1時,R0=R1-R2;當R0>1時,R0=R1+R2。:
代碼清單3.5
NAME JUMP
PUBLIC main
B main
Num EQU 2 ;跳轉表格的入口數
RSEG CODE
CODE32
main: MOV R0,#0 ;如下設置3個參數
MOV R1,#3
MOV R2,#2
BL arithfunc ;調用子程序
stop: B stop ;程序中止
arithfunc:
CMP R0,#Num ;比較參數
BHS Doadd ;若R0>=2,則執行加法
ADR R3,jumptable ;裝載跳轉表格標號地址
LDR PC,[R3,R0,LSL #2] ;跳到相應子程序入口地址處
Jumptable:
DCD Doadd ;Doadd子程序的入口地址
DCD Dosub ;Dosub子程序的入口地址
Doadd: ADD R0,R1,R2 ;=0或>1時執行的操做
MOV PC,LR
Dosub: SUB R0,R1,R2 ;=1時執行的操做
MOV PC,LR
ENDMOD
END
在應用系統的程序設計中,若全部的編程任務均用匯編語言來完成,其工做量是可想而知的,同時,不利於系統升級或應用軟件移植,事實上,ARM體系結構支持C/C+以及與彙編語言的混合編程,在一個完整的程序設計的中,除了初始化部分用匯編語言完成之外,其主要的編程任務通常都用C/C++ 完成。
彙編語言與C/C++的混合編程一般有如下幾種方式:
1. 在C/C++代碼中嵌入彙編指令。
在ARM C中,能夠使用關鍵字__arm來標識一段彙編指令程序。格式以下:
__asm
{
彙編指令序列
}
便可在C語言源程序中直接執行ARM彙編指令。
2. 在彙編程序和C/C++的程序之間進行變量的互訪。
3. 彙編程序、C/C++程序間的相互調用。
能夠把彙編程序和C/C++程序中須要共享的變量或函數用PUBLIC或extern關鍵字分別聲明爲全局變量或全局函數,而後在其它程序文件中便可進行訪問和調用。可是從好的編程風格來講,最好儘可能減小全局變量和全局函數的使用。
混合編程中,必須遵照必定的調用規則,如物理寄存器的使用、參數的傳遞等。ARM專門爲此制定了一個標準ATPCS(ARM-Thumb Procedure Call Standard,ARM-Thumb過程調用標準)。對於初學者來講,這是很是煩瑣的,在實際工做中也沒有太多必要。
在實際的編程應用中,使用較多的方式是:系統程序的初始化部分用匯編語言完成,而後用C/C++完成主要的編程任務,程序在執行時首先完成初始化過程,而後跳轉到C/C++程序代碼中。彙編程序和C/C++程序之間通常沒有參數的傳遞,也沒有頻繁的相互調用,所以,整個程序的結構顯得相對簡單,容易理解。
如下是一個這種結構程序的基本示例。該程序很是簡單,創建一個工程asm_c.eww,工程中包括一個彙編語言程序文件init.s79和一個C語言程序文件hello.c。
代碼清單3.6——init.s79文件
NAME INIT
PUBLIC main
EXTERN Main ;聲明引入C程序的Main()函數
B main
RSEG CODE
CODE32
main:
NOP ;此處能夠插入用戶本身編寫的系統初始化代碼
B Main ;轉向C語言程序
ENDMOD
END
代碼清單3.7——hello.c文件:
#include <stdio.h>
/*注意此處C語言程序的入口函數是大小寫敏感的Main()函數,而不是經常使用的main()函數。這是爲了跟彙編程序中的main入口區別開,以避免形成工程有兩個程序入口。*/
int Main(void)
{
printf("Hello, world!\n");
}
基於ARM內核的芯片多數爲複雜的片上系統,這種複雜系統裏的多數硬件模塊都是能夠配置的,須要由軟件來設置其須要的工做狀態。因爲C語言具備模塊性和可移植性的特色,大部分基於ARM的應用系統程序都採用C語言編寫。可是當系統復位啓動時,在進入C語言的main函數以前,須要有一段啓動程序來完成對存儲器配置、地址重映射和ARM芯片內部集成外圍功能初始化等工做。這類工做直接面對處理器內核和硬件控制器進行編程,用C語言較難實現,所以通常採用彙編語言編寫。
ARM內核的處理器在復位後,從0x00000000地址處開始讀取指令。實現啓動最簡單的方法是將應用程序放在映射空間地址爲0的ROM中。這樣當執行第1條指令時,應用程序就從0x00000000處開始執行。但這種方法有不少缺點:ROM的存儲寬度較小且速度較慢,會下降系統啓動和處理器對異常處理的速度;異常向量表放在ROM中,程序將沒法修改向量表,所以常將地址爲0的空間映射成RAM,但RAM中的程序掉電沒法保存,所以必須將ROM映射爲0地址,以保證有效的復位向量,而後再使用重映射命令將RAM映射爲0地址,ROM映射到其餘地址空間,並將異常向量從ROM複製到RAM中。
編寫啓動程序應遵循如下通常規則:
1. 設置入口指針
啓動程序首先必須定義入口指針,並且整個應用程序只有一個入口指針,一般應用程序的入口地址爲0。
2. 設置異常向量
基於ARM7TDMI內核的處理器共支持7種異常,異常處理地址存放在地址0處的異常向量表中,共8×4字節的空間。異常向量表的內容參見2.4.2節。
異常向量表一般放在存儲器底部,每一個異常分配4個字節的空間。每一個向量入口包含一條跳轉指令或加載PC的指令,以執行適當的轉移到具體的異常處理程序。若是ROM定位於0地址,則向量表由一系列固定的用以指向每一個異常的指令組成;不然向量必須被動態初始化。能夠在啓動程序中添加一段代碼,使其在運行時將向量表拷貝到0地址開始的存儲器空間。對於沒有使用的異常,使其指向一個只含返回指令的啞函數,以防止錯誤異常引發系統混亂。
3. 初始化片內集成外圍功能
因爲ARM公司僅設計內核並出售給其它半導體廠商,不一樣的廠商購買內核受權後加入本身的外圍功能,從而致使ARM核處理器芯片豐富多樣,但也使得不一樣芯片的啓動代碼在這一部分差異很大。編寫這一部分時應根據芯片和應用系統要求對它們進行合適的初始化。比較重要的操做通常有:外部總線接口的初始化、配置時鐘鎖相環、配置中斷控制器、禁用看門狗電路等。
4. 初始化存儲系統
有些ARM核芯片可經過對寄存器編程來初始化系統存儲器,而對於較複雜系統一般由存儲管理單元MMU來管理內存空間。爲正確運行應用程序,在初始化期間應將系統須要讀寫的數據和變量從ROM拷貝到RAM中;一些要求快速響應的程序,例如中斷處理程序,也須要在RAM中運行;若是使用Flash,對Flash的擦除和寫入操做也必定要在RAM中運行。
5. 初始化堆棧寄存器
系統堆棧初始化取決於用戶使用了哪些中斷,以及系統須要處理哪些錯誤類型。通常來講管理模式堆棧必須初始化。若是使用IRQ中斷,則IRQ堆棧必須初始化,而且必須在容許中斷以前進行。若是使用FIQ中斷,則FIQ堆棧也必須初始化,而且必須在容許中斷以前進行。通常在簡單的嵌入式系統中不使用停止狀態堆棧和未定義指令堆棧,但爲了調試方便仍是將其初始化。若是系統使用DRAM或其它外設,還須要設置相關寄存器,以肯定其刷新頻率、數據總線寬度等信息。
6. 改變處理器模式和狀態
此時能夠經過清除CPSR寄存器中的中斷控制位來容許中斷,這裏是安全開啓中斷的最先地方。這個階段處理器仍處於管理模式下。若是程序須要在用戶模式下運行,能夠在此處切換到用戶模式並初始化用戶模式堆棧指針。
7. 跳轉到C語言主程序
在從啓動程序跳轉到C語言程序的main函數以前,還須要初始化數據存儲空間。一般是加入一段循環代碼對數據存儲空間清0。這樣作的主要緣由是C語言中沒有初值的變量默認值均爲0。已經初始化變量的初值必須從ROM中複製到RAM中,其它變量的初值必須爲0。
下面給出了IAR EWARM軟件包提供的通常啓動程序代碼,實際應用中能夠根據具體芯片及應用系統要求進行適當修改,以適應不一樣場合的須要。
代碼清單3.8——IAR EWARM啓動代碼
;-----------------------------------------------------------------------------
; 文件中標號的命名規則:
; ?xxx - 僅能由彙編語言訪問的外部標號
; __xxx - 可由C語言訪問或定義的外部標號
; xxx - 單個模塊中的局部標號(注意,本文件包含多個模塊)
; main - 用戶程序的起點
;---------------------------------------------------------------
; 適用於整個文件的宏和模式定義
;---------------------------------------------------------------
; 模式,對應於CPSR寄存器的0~5位
MODE_BITS DEFINE 0x1F ; 用於CPSR模式的位屏蔽
USR_MODE DEFINE 0x10 ; 用戶模式
FIQ_MODE DEFINE 0x11 ; FIQ模式
IRQ_MODE DEFINE 0x12 ; IRQ模式
SVC_MODE DEFINE 0x13 ; 管理模式
ABT_MODE DEFINE 0x17 ; 停止模式
UND_MODE DEFINE 0x1B ; 未定義指令模式
SYS_MODE DEFINE 0x1F ; 系統模式
;---------------------------------------------------------------
; ?RESET
; 復位向量。一般INTVEC段被連接到地址0。爲程序調試方便,也能夠放在其它地址
;---------------------------------------------------------------
MODULE ?RESET
COMMON INTVEC:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; 復位後始終爲ARM模式
org 0x00
__program_start
ldr pc,[pc,#24] ; 絕對跳轉地址範圍爲4GB
; ldr b,?cstartup ; 相對跳轉容許重映射,限於32MB
; 能夠去掉如下指令前的註釋分號來容許異常向量
; 也能夠在C語言中採用預編譯命令「#pragma vector」
org 0x04
; ldr pc,[pc,#24] ; 跳轉到undef_handler
org 0x08
; ldr pc,[pc,#24] ; 跳轉到swi_handler
org 0x0c
; ldr pc,[pc,#24] ; 跳轉到prefetch_handler
org 0x10
; ldr pc,[pc,#24] ; 跳轉到data_handler
org 0x18
; ldr pc,[pc,#24] ; 跳轉到irq_handler
org 0x1c
; ldr pc,[pc,#24] ; 跳轉到fiq_handler
; 用於「ldr pc」指令的常數表入口定位於0x20
; 異常向量能夠用C語言的預編譯命令「#pragma vector」指定,也能夠
; 在如下dc32指令後面填入向量地址。向量地址爲ARM向量號+20
org 0x20
dc32 ?cstartup
org 0x24
; dc32 undef_handler
org 0x28
; dc32 swi_handler
org 0x2c
; dc32 prefetch_handler
org 0x30
; dc32 data_handler
org 0x38
; dc32 irq_handler
org 0x3c
; dc32 fiq_handler
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG ABT_STACK:DATA:NOROOT(2)
RSEG UND_STACK:DATA:NOROOT(2)
RSEG FIR_STACK:DATA:NOROOT(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; 從這裏開始執行
; 復位後爲ARM管理模式,禁止中斷
CODE32
?cstartup
; 須要時在這裏加入創建堆棧指針以前的初始化指令
; 初始化堆棧指針
; 如下方式可用於任何異常堆棧:FIQ, IRQ, SVC, ABT, UND, SYS.
; 用戶模式使用與SYS模式相同的堆棧
; 堆棧段必須在連接器命令文件中定義,而且已經在上面聲明
mrs r0,cpsr ; 原PSR值
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#IRQ_MODE ; 置IRQ模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(IRQ_STACK)&0xFFFFFFF8 ; IRQ_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#ABT_MODE ; 置Abort模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(ABT_STACK)&0xFFFFFFF8 ; ABT_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#SVC_MODE ; 置Supervisor模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(SVC_STACK) & 0xFFFFFFF8 ; SVC_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#UND_MODE ; 置Undefined模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(UND_STACK) & 0xFFFFFFF8 ; FIR_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#FIQ_MODE ; 置FIR模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(FIR_STACK) & 0xFFFFFFF8 ; FIR_STACK結束
bic r0,r0,#MODE_BITS ; 清除模式位
orr r0,r0,#SYS_MODE ; 置System模式位
msr cpsr_c,r0 ; 改變模式
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; CSTACK結束
#ifdef __ARMVFP__
; 容許VFP協處理器
mov r0, #0x40000000 ; 置VFP的EN位
fmxr fpexc, r0 ; FPEXC, 清除其它
; 將緩衝區清0以禁止下溢出。爲知足IEEE 754標準,應刪除該指令並安裝合適的異常句柄
mov r0, #0x01000000 ; 置VFP的FZ位
fmxr fpscr, r0 ; FPSCR, 清除其它
#endif
; 在這裏能夠添加更多的用戶自定義初始化指令
; 跳轉到?main標號的地方,繼續IAR系統的啓動程序
ldr r0,=?main
bx r0
LTORG
ENDMOD
END
3.1 ARM7TDMI有幾種尋址方式?LDR R1,[R0,#0x04]屬於哪一種尋址方式?
3.2 ARM指令的條件碼有多少個?默認條件碼是什麼?
3.3 ARM指令中第二個操做數有哪幾種形式?
3.4 請指出MOV指令與LDR加載指令的區別及用途.
3.5 CMP指令的功能是什麼?寫一個程序,判斷R1的值是否大於0x30,是則將R1減去0x30。
3.6 調用子程序是用B仍是用BL指令?請寫出返回子程序的指令。
3.7 ARM狀態與Thumb狀態的切換指令是什麼?請舉例說明。
3.8 Thumb狀態與ARM狀態的寄存器有區別嗎?Thumb指令對哪些寄存器的訪問受到必定限制?
3.9 Thumb指令集的堆棧入棧、出棧指令是哪兩條?
3.10 把下面的C代碼轉換成彙編代碼。數組a和b分別存放在以0x4000和0x5000爲起始地址的存儲區內,類型爲long型(32位)。
for(i=0;i<8;i++)
{
a[i] = b[7-i];
}
3.11 編寫程序,將R1的高8位傳送到R2的低8位
3.12 編寫一段64位加法運算的程序,要求知足:[R1:R0]+[R3:R2],結果存入[R1:R0]中
3.13 編寫程序將地址0x0000 1000到0x0000 1030的數據所有搬遷到0x0000 2000到0x0000 2030的區域中,並將源數據區清零。
處理器的「體系結構」指從程序員角度觀察到的處理器的組織方式,因此又稱爲處理器的編程模型。其主要內容爲處理器內的寄存器組織、對存儲器的尋址方式、指令系統等。本章將介紹ARM7TDMI程序員模型、工做狀態與工做模式、ARM和Thumb狀態的寄存器組織、存儲器組織結構、異常及協處理器接口等一些基本概念。本章還要講述ARM的編程基礎,如ARM微處理器的基本工做原理、與程序設計相關的基本技術細節等。
LPC2400系列處理器包括LPC2468/LPC2470/LPC2478等多款芯片,是基於支持實時仿真和跟蹤的16/32位ARM7TDMI-S內核的微控制器,它與全部NXP LPC 2000處理器具備相同的存儲器映射、中斷向量控制、Flash編程和更新機制,以及調試和仿真功能。LPC2468/LPC2478的512KB大容量嵌入式高速Flash存儲器具備128位寬度的存儲器接口和獨特的加速結構,使得32位代碼可以在最高時鐘頻率72MHz下運行。16位Thumb模式能夠將代碼規模下降30%以上,而性能損失卻很小。LPC2470/LPC2478芯片內部還集成了LCD接口支持(最高1024×768像素、15階灰度單色和每像素24位真彩色TFT面板),使得這兩款芯片能夠普遍應用於各類手持式設備中。
LPC2400系列處理器擁有豐富的片上資源和外設接口。這一系列芯片的共同特性有:
-ARM7TDMI-S內核,最高72MHz主頻;
-98KB的片內靜態存儲器,其中64KB的片內SRAM,16KB SRAM用於以太網,16KB SRAM用於DMA控制器(也可用於USB控制器),2KB SRAM用於RTC實時時鐘;
-512KB片內Flash程序存儲器,片內Boot實現IAP和ISP片內Flash編程;
-可配置的外部存儲器接口,最多支持8個Bank,支持外部RAM、ROM和Flash存儲器擴展,每一個Bank最大可支持到256MB,可支持8/16/32位字寬;
-高級向量中斷控制器,支持32個向量中斷,可配置優先級和向量地址;
-通用AHB DMA控制器(GPDMA)能夠用於支持SSP、I2S和SD/MMC接口;
-10/100M以太網MAC接口;
-多個串行接口,包括4路UART、3路I2C串行總線接口和1個SPI接口;
-10位A/D和D/A轉換器,轉換時間低至2.44微秒;
-USB device/host/OTG接口;
-2個CAN總線接口;
-4個32位的定時器、2個PWM脈衝調製單元(每一個6路輸出)、實時時鐘和看門狗;
-160個高速GPIO端口(可承受5V電壓),4個獨立外部中斷引腳;
-標準ARM調試接口,兼容各類現有的調試工具;
-片內晶振頻率範圍1~24MHz;
-4個低功耗模式:空閒、睡眠、掉電和深度掉電模式;
-供電電壓3.3V(3.0V~3.6V)。
在LPC2400系列芯片中,LPC2468是LPC2478的無LCD控制器版本,LPC2470是LPC2478的無片內Flash版本,芯片的大多數特性是徹底相同的。因此在後面的章節中,本書一概採用LPC2478芯片爲例進行講解,請讀者在實際工做中注意具體芯片的差異。
LPC2400系列處理器包含一個支持仿真的ARM7TDMI-S CPU、與片內存儲器控制器接口的ARM7局部總線、與中斷控制器接口的AMBA高性能總線(AHB總線)和鏈接片內外設功能的AMBA外設總線(APB總線)。存儲模式爲小端模式。
AHB總線和APB總線都是ARM公司推出的AMBA片上總線規範的一部分。AHB(Advanced High performance Bus)系統總線主要用於高性能模塊(如CPU、DMA和DSP等)之間的鏈接,通常用於片內高性能高速度的外設,如:外部存儲器、USB接口、DMA控制器、以太網控制器、LCD液晶屏控制器以及高速GPIO控制器等。LPC2400中的AHB外設一共分配了2MB的地址範圍,它位於4GB ARM存儲器空間的最頂端。每一個AHB外設都分配了16KB的地址空間。
LPC2400的外設功能模塊都鏈接到APB總線。APB(Advanced Peripheral Bus)外圍總線主要用於低帶寬的周邊外設之間的鏈接,如:UART、I2C、SPI、I2S、A/D、D/A、CAN等等。APB總線與AHB總線之間經過AHB到APB的橋相連。APB外設也分配了2MB的地址範圍,每一個APB外設在APB地址空間內都分配了16KB的地址空間。
片內外設與器件引腳的鏈接由引腳鏈接模塊控制。軟件能夠經過控制該模塊讓引腳與特定的片內外設相鏈接。
LPC2400的結構框圖如圖4.1所示。
圖4.1 LPC2400結構框圖
LPC2400系列處理器共有208個引腳,通常提供兩種封裝形式:LQFP208和TFBGA208。其管腳封裝如圖4.2所示。
LQFP208 FBGA208
圖4.2 LPC2400系列處理器管腳封裝圖
LQFP指封裝本體厚度爲1.4mm的薄型QFP(四側引腳扁平封裝quad flat package),它是一種表面貼裝型封裝,引腳從四個側面引出呈L型,每一個側面52個引腳,引腳號分別爲1~5二、53~10四、105~15六、157~208。FBGA是塑料封裝的BGA(Ball Grid Array Package),即球柵陣列封裝,其引腳都在芯片底部,用英文字母行和數字列標識。因爲LPC2400系列處理器在實際使用中更多使用QFP封裝,本節引腳介紹以QFP封裝爲準。
從功能上,LPC2400的208個引腳分爲P0口、P1口、P2口、P3口、P4口,以及電源、復位、晶振和其它管腳幾部分。下面對這幾個部分分別進行介紹。
1. P0口: P0口是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P0口管腳描述如表4.1所示。
表4.1 LPC2400的P0口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P0[0] |
94 |
I/O |
P0[0]:GPIO口 |
I |
RD1:CAN1接收器輸入 |
||
O |
TXD3:UART3發送輸出端 |
||
I/O |
SDA1:I2C1數據輸入/輸出 |
||
P0[1] |
96 |
I/O |
P0[1]:GPIO口 |
O |
TD1:CAN1發送器輸出 |
||
I |
RXD3:UART3接收輸入端 |
||
I/O |
SCL1:I2C1時鐘輸入/輸出 |
||
P0[2] |
202 |
I/O |
P0[2]:GPIO口 |
O |
TXD0:UART0發送輸出端 |
||
P0[3] |
204 |
I/O |
P0[3]:GPIO口 |
I |
RXD0:UART0接收輸入端 |
||
P0[4] |
168 |
I/O |
P0[4]:GPIO口 |
I/O |
I2SRX_CLK:I2S總線接收時鐘 |
||
I |
RD2:CAN2接收輸入端 |
||
I |
CAP2[0]:Timer2的捕獲輸入通道0 |
||
P0[5] |
166 |
I/O |
P0[5]:GPIO口 |
I/O |
I2SRX_WS:I2S總線接收字選擇 |
||
I |
TD2:CAN2發送輸出端 |
||
I |
CAP2[1]:Timer2的捕獲輸入通道1 |
||
P0[6] |
164 |
I/O |
P0[6]:GPIO口 |
I/O |
I2SRX_SDA:I2S總線數據接收 |
||
I/O |
SSEL1:SSP1從機選擇 |
||
O |
MAT2[0]:Timer2的匹配輸出通道0 |
||
P0[7] |
162 |
I/O |
P0[7]:GPIO口 |
I/O |
I2STX_CLK:I2S總線發送時鐘 |
||
I/O |
SCK1:SSP1串行時鐘 |
||
O |
MAT2[1]:Timer2的匹配輸出通道1 |
||
P0[8] |
160 |
I/O |
P0[8]:GPIO口 |
I/O |
I2STX_WS:I2S總線發送字選擇 |
||
I/O |
MISO1:SSP1主機輸入從機輸出 |
||
O |
MAT2[2]:Timer2的匹配輸出通道2 |
||
P0[9] |
158 |
I/O |
P0[9]:GPIO口 |
I/O |
I2STX_SDA:I2S總線數據發送 |
||
I/O |
MOSI1:SSP1主機輸出從機輸入 |
||
O |
MAT2[3]:Timer2的匹配輸出通道3 |
||
P0[10] |
98 |
I/O |
P0[10]:GPIO口 |
O |
TXD2:UART2發送輸出端 |
||
I/O |
SDA2:I2C2數據輸入/輸出 |
||
O |
MAT3[0]:Timer3的匹配輸出通道0 |
||
P0[11] |
100 |
I/O |
P0[11]:GPIO口 |
I |
RXD2:UART2接收輸入端 |
||
I/O |
SCL2:I2C2時鐘輸入/輸出 |
||
O |
MAT3[1]:Timer3的匹配輸出通道1 |
||
P0[12] |
41 |
I/O |
P0[12]:GPIO口 |
O |
USB_PPWR2:USB端口2端口電源使能 |
||
I/O |
MISO1:SSP1主機輸入從機輸出 |
||
I |
AD0[6]:A/D轉換器0輸入6 |
||
P0[13] |
45 |
I/O |
P0[13]:GPIO口 |
O |
USB_UP_LED2:USB端口2LED |
||
I/O |
MOSI1:SSP1主機輸出從機輸入 |
||
I |
AD0[7]:A/D轉換器0輸入7 |
||
P0[14] |
69 |
I/O |
P0[14]:GPIO口 |
O |
USB_HSTEN2:USB端口2主機使能 |
||
O |
USB_CONNECT2:USB端口2軟件鏈接控制 |
||
I/O |
SSEL1:SSP1從機選擇 |
||
P0[15] |
128 |
I/O |
P0[15]:GPIO口 |
O |
TXD1:UART1發送輸出端 |
||
I/O |
SCK0:SSP0串行時鐘 |
||
I/O |
SCK:SPI串行時鐘 |
||
P0[16] |
130 |
I/O |
P0[16]:GPIO口 |
I |
RXD1:UART1接收輸入端 |
||
I/O |
SSEL0:SSP0從機選擇 |
||
I/O |
SSEL:SPI從機選擇 |
||
P0[17] |
126 |
I/O |
P0[17]:GPIO口 |
I |
CTS1:UART1清除發送輸入端 |
||
I/O |
MISO0:SSP0主機輸入從機輸出 |
||
I/O |
MISO:SPI主機輸入從機輸出 |
||
P0[18] |
124 |
I/O |
P0[18]:GPIO口 |
I |
DCD1:UART1數據載波檢測輸入端 |
||
I/O |
MOSI0:SSP0主機輸出從機輸入 |
||
I/O |
MOSI:SPI主機輸出從機輸入 |
||
P0[19] |
122 |
I/O |
P0[19]:GPIO口 |
I |
DSR1:UART1數據設置就緒端 |
||
O |
MCICLK:SD/MMC接口時鐘輸出線 |
||
I/O |
SDA1:I2C1數據輸入/輸出 |
||
P0[20] |
120 |
I/O |
P0[20]:GPIO口 |
O |
DTR1:UART1數據終止就緒端 |
||
I/O |
MCICMD:SD/MMC接口命令線 |
||
I/O |
SCL1:I2C1時鐘輸入/輸出 |
||
P0[21] |
118 |
I/O |
P0[21]:GPIO口 |
I |
RI1:UART1鈴響指示輸入端 |
||
O |
MCIPWR:SD/MMC電源供應使能 |
||
I |
RD1:CAN1接收輸入端 |
||
P0[22] |
116 |
I/O |
P0[22]:GPIO口 |
O |
RTS1:UART1請求發送輸出端 |
||
I/O |
MCIDAT0:SD/MMC接口數據線0 |
||
O |
TD1:CAN1發送輸出端 |
||
P0[23] |
18 |
I/O |
P0[23]:GPIO口 |
I |
AD0[0]:A/D轉換器0輸入0 |
||
I/O |
I2SRX_CLK:I2S總線接收時鐘 |
||
I |
CAP3[0]:Timer3的捕獲輸入通道0 |
||
P0[24] |
16 |
I/O |
P0[24]:GPIO口 |
I |
AD0[1]:A/D轉換器0輸入1 |
||
I/O |
I2SRX_WS:I2S總線字選擇 |
||
I |
CAP3[1]:Timer3的捕獲輸入通道1 |
||
P0[25] |
14 |
I/O |
P0[25]:GPIO口 |
I |
AD0[2]:A/D轉換器0輸入2 |
||
I/O |
I2SRX_SDA:I2S總線數據接收 |
||
O |
TXD3:UART3發送輸出端 |
||
P0[26] |
12 |
I/O |
P0[26]:GPIO口 |
I |
AD0[3]:A/D轉換器0輸入3 |
||
O |
AOUT:D/A轉換器輸出 |
||
I |
RXD3:UART3接收輸入端 |
||
P0[27] |
50 |
I/O |
P0[27]:GPIO口 |
I/O |
SDA0:I2C0數據輸入/輸出 |
||
P0[28] |
48 |
I/O |
P0[28]:GPIO口 |
I/O |
SCL0:I2C0時鐘輸入/輸出 |
||
P0[29] |
61 |
I/O |
P0[29]:GPIO口 |
I/O |
USB_D+1:USB端口1雙向D+線 |
||
P0[30] |
62 |
I/O |
P0[30]:GPIO口 |
I/O |
USB_D-1:USB端口1雙向D-線 |
||
P0[31] |
51 |
I/O |
P0[31]:GPIO口 |
I/O |
USB_D+2:USB端口2雙向D+線 |
2. P1口: P1口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P1口管腳描述如表4.2所示。
表4.2 LPC2400的P1口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P1[0] |
196 |
I/O |
P1[0]:GPIO口 |
O |
ENET_TXD0:以太網發送數據0(RMII/MII接口) |
||
P1[1] |
194 |
I/O |
P1[1]:GPIO口 |
O |
ENET_TXD1:以太網發送數據1(RMII/MII接口) |
||
P1[2] |
185 |
I/O |
P1[2]:GPIO口 |
O |
ENET_TXD2:以太網發送數據2(RMII/MII接口) |
||
O |
MCICLK:SD/MMC接口時鐘輸出線 |
||
O |
PWM0[1]:脈寬調製器0輸出1 |
||
P1[3] |
177 |
I/O |
P1[3]:GPIO口 |
O |
ENET_TXD3:以太網發送數據3(RMII/MII接口) |
||
O |
MCICMD:SD/MMC接口命令線 |
||
O |
PWM0[2]:脈寬調製器0輸出2 |
||
P1[4] |
192 |
I/O |
P1[4]:GPIO口 |
O |
ENET_TX_EN:以太網發送數據使能(RMII/MII接口) |
||
P1[5] |
156 |
I/O |
P1[5]:GPIO口 |
O |
ENET_TX_ER:以太網發送數據出錯(MII接口) |
||
O |
MCIPWR:SD/MMC電源供應使能 |
||
O |
PWM0[3]:脈寬調製器0輸出3 |
||
P1[6] |
171 |
I/O |
P1[6]:GPIO口 |
I |
ENET_TX_CLK:以太網發送時鐘(MII接口) |
||
I/O |
MCIDAT0:SD/MMC接口數據線0 |
||
O |
PWM0[4]:脈寬調製器0輸出4 |
||
P1[7] |
153 |
I/O |
P1[7]:GPIO口 |
I |
ENET_COL:以太網衝突檢測(MII接口) |
||
I/O |
MCIDAT1:SD/MMC接口數據線1 |
||
O |
PWM0[5]:脈寬調製器0輸出5 |
||
P1[8] |
190 |
I/O |
P1[8]:GPIO口 |
I |
ENET_CRS_DV/ENET_CRS:以太網載波檢測/數據有效(RMII接口)/以太網載波檢測(MII接口) |
||
P1[9] |
188 |
I/O |
P1[9]:GPIO口 |
I |
ENET_RXD0:以太網接收數據0(RMII/MII接口) |
||
P1[10] |
186 |
I/O |
P1[10]:GPIO口 |
I |
ENET_RXD1:以太網接收數據1(RMII/MII接口) |
||
P1[11] |
163 |
I/O |
P1[11]:GPIO口 |
I |
ENET_RXD2:以太網接收數據2(RMII/MII接口) |
||
I/O |
MCIDAT2:SD/MMC接口數據線2 |
||
O |
PWM0[6]:脈寬調製器0輸出6 |
||
P1[12] |
157 |
I/O |
P1[12]:GPIO口 |
I |
ENET_RXD3:以太網接收數據3(RMII/MII接口) |
||
I/O |
MCIDAT3:SD/MMC接口數據線3 |
||
I |
PCAP0[0]:脈寬調製器0捕獲輸入通道0 |
||
P1[13] |
147 |
I/O |
P1[13]:GPIO口 |
I |
ENET_RX_DV:以太網接收數據有效(MII接口) |
||
P1[14] |
184 |
I/O |
P1[14]:GPIO口 |
I |
ENET_RX_ER:以太網接收錯誤(MII接口) |
||
P1[15] |
182 |
I/O |
P1[15]:GPIO口 |
I |
ENET_REF_CLK/ENET_RX_CLK:以太網參考時鐘(RMII接口)/以太網接收時鐘(MII接口) |
||
P1[16] |
180 |
I/O |
P1[16]:GPIO口 |
I |
ENET_MDC:以太網MIIM時鐘 |
||
P1[17] |
178 |
I/O |
P1[17]:GPIO口 |
I/O |
ENET_MDIO:以太網MI數據輸入輸出 |
||
P1[18] |
66 |
I/O |
P1[18]:GPIO口 |
O |
USB_UP_LED1:USB端口1LED |
||
O |
PWM1[1]:脈寬調製器1輸出1 |
||
I |
CAP1[0]:Timer1捕獲輸入通道0 |
||
P1[19] |
68 |
I/O |
P1[19]:GPIO口 |
O |
USB_TX_E1:USB端口1發送使能信號(OTG收發器) |
||
O |
USB_PPWR1:USB端口1端口電源使能信號 |
||
I |
CAP1[1]:Timer1捕獲輸入通道1 |
||
P1[20] |
70 |
I/O |
P1[20]:GPIO口 |
O |
USB_TX_DP1:USB端口1D+數據發送(OTG收發器) |
||
O |
PWM1[2]:脈寬調製器1輸出2 |
||
I/O |
SCK0:SSP0串行時鐘 |
||
P1[21] |
72 |
I/O |
P1[21]:GPIO口 |
O |
USB_TX_DM1:USB端口1D-數據發送(OTG收發器) |
||
O |
PWM1[3]:脈寬調製器1輸出3 |
||
I/O |
SSEL0:SSP0從機選擇 |
||
P1[22] |
74 |
I/O |
P1[22]:GPIO口 |
I |
USB_RCV1:USB端口1差分數據接收(OTG收發器) |
||
I |
USB_PWRD1:USB端口1電源狀態(主機電源開關) |
||
O |
MAT1[0]:Timer1匹配輸出通道0 |
||
P1[23] |
76 |
I/O |
P1[23]:GPIO口 |
I |
USB_RX_DP1:USB端口1D+數據接收(OTG收發器) |
||
O |
PWM1[4]:脈寬調製器1輸出4 |
||
I/O |
MISO0:SSP0主機輸入從機輸出 |
||
P1[24] |
78 |
I/O |
P1[24]:GPIO口 |
I |
USB_RX_DM1:USB端口1D-數據接收(OTG收發器) |
||
O |
PWM1[5]:脈寬調製器1輸出5 |
||
I/O |
MOSI0:SSP0主機輸出從機輸入 |
||
P1[25] |
80 |
I/O |
P1[25]:GPIO口 |
O |
USB_LS1:USB端口1低速狀態(OTG收發器) |
||
O |
USB_HSTEN1:USB端口1主機使能狀態 |
||
O |
MAT1[1]:Timer1匹配輸出通道1 |
||
P1[26] |
82 |
I/O |
P1[26]:GPIO口 |
O |
USB_SSPND1:USB端口1總線懸掛狀態(OTG收發器) |
||
O |
PWM1[6]:脈寬調製器1輸出6 |
||
I |
CAP0[0]:Timer0捕獲輸入通道0 |
||
P1[27] |
88 |
I/O |
P1[27]:GPIO口 |
I |
USB_INT1:USB端口1OTG ATX中斷(OTG收發器) |
||
I |
USB_OVRCR1:USB端口1過流狀態 |
||
I |
CAP0[1]:Timer0捕獲輸入通道1 |
||
P1[28] |
90 |
I/O |
P1[28]:GPIO口 |
I/O |
USB_SCL1:USB端口1I2C串行時鐘(OTG收發器) |
||
I |
PCAP1[0]:脈寬調製器1捕獲輸入通道0 |
||
O |
MAT0[0]:Timer0匹配輸出通道0 |
||
P1[29] |
92 |
I/O |
P1[29]:GPIO口 |
I/O |
USB_SDA1:USB端口1I2C串行數據(OTG收發器) |
||
I |
PCAP1[1]:脈寬調製器1捕獲輸入通道1 |
||
O |
MAT0[1]:Timer0匹配輸出通道1 |
||
P1[30] |
42 |
I/O |
P1[30]:GPIO口 |
I |
USB_PWRD2:USB端口2電源狀態 |
||
I |
VBUS:指示USB總線當前電源。注意:當USB復位時這個信號必須爲高電平 |
||
I |
AD0[4]:A/D轉換器0輸入4 |
||
P1[31] |
40 |
I/O |
P1[31]:GPIO口 |
I |
USB_OVRCR2:USB端口2過流狀態 |
||
I/O |
SCK1:SSP1串行時鐘 |
||
I |
AD0[5]:A/D轉換器0輸入5 |
3. P2口: P2口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P2口管腳描述如表4.3所示。
表4.3 LPC2400的P2口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P2[0] |
154 |
I/O |
P2[0]:GPIO口 |
O |
PWM1[1]:脈寬調製器1輸出1 |
||
O |
TXD1:UART1發送輸出端 |
||
O |
TRACECLK/LCDPWR:跟蹤時鐘/LCD面板電源使能 |
||
P2[1] |
152 |
I/O |
P2[1]:GPIO口 |
O |
PWM1[2]:脈寬調製器1輸出2 |
||
I |
RXD1:UART1接收輸入端 |
||
O |
PIPESTAT0/LCDLE:流水線狀態位0/LCD行結束信號 |
||
P2[2] |
150 |
I/O |
P2[2]:GPIO口 |
O |
PWM1[3]:脈寬調製器1輸出3 |
||
I |
CTS1:UART1清除發送輸入端 |
||
O |
PIPESTAT1/LCDCP:流水線狀態位1/LCD面板時鐘 |
||
P2[3] |
144 |
I/O |
P2[3]:GPIO口 |
O |
PWM1[4]:脈寬調製器1輸出4 |
||
I |
DCD1:UART1數據載波檢測輸入端 |
||
O |
PIPESTAT2/LCDFP:流水線狀態位2/LCD幀脈衝(STN)垂直同步脈衝(TFT) |
||
P2[4] |
142 |
I/O |
P2[4]:GPIO口 |
O |
PWM1[5]:脈寬調製器1輸出5 |
||
I |
DSR1:UART1數據設置就緒端 |
||
O |
TRACESYNC/LCDAC:跟蹤同步/LCD交流斜線驅動(STN)數據使能輸出(TFT) |
||
P2[5] |
140 |
I/O |
P2[5]:GPIO口 |
O |
PWM1[6]:脈寬調製器1輸出6 |
||
O |
DTR1:UART1數據終止就緒端 |
||
O |
TRACEPKT0/LCDAC:跟蹤分組位0/LCD行同步脈衝(STN)水平同步脈衝(TFT) |
||
P2[6] |
138 |
I/O |
P2[6]:GPIO口 |
I |
PCAP1[0]:脈寬調製器1捕獲輸入通道0 |
||
I |
RI1:UART1響鈴指示輸入端 |
||
O |
TRACEPKT1/LCD[0]/LCD[4]:跟蹤分組位1/LCD數據 |
||
P2[7] |
136 |
I/O |
P2[7]:GPIO口 |
I |
RD2:CAN2接收輸入 |
||
O |
RTS1:UART1請求發送輸出端 |
||
O |
TRACEPKT2/LCD[1]/LCD[5]:跟蹤分組位1/LCD數據 |
||
P2[8] |
134 |
I/O |
P2[8]:GPIO口 |
O |
TD2:CAN2發送輸出 |
||
O |
TXD2:UART2接收輸入端 |
||
O |
TRACEPKT3/LCD[2]/LCD[6]:跟蹤分組位3/LCD數據 |
||
P2[9] |
132 |
I/O |
P2[9]:GPIO口 |
O |
USB_CONNECT1:USB1軟鏈接控制 |
||
I |
RXD2:UART2接收輸入 |
||
I |
EXTINT0/LCD[3]/LCD[7]:外部觸發中斷輸入/LCD數據 |
||
P2[10] |
110 |
I/O |
P2[10]:GPIO口 |
I |
EINT0:外部中斷0輸入 |
||
P2[11] |
108 |
I/O |
P2[11]:GPIO口 |
I/O |
EINT1:外部中斷1輸入/LCDCLKIN:LCD時鐘 |
||
I/O |
MCIDAT1:SD/MMC接口數據線1 |
||
I/O |
I2STX_CLK:I2S傳輸時鐘。 |
||
P2[12] |
106 |
I/O |
P2[12]:GPIO口 |
I/O |
EINT2:外部中斷2輸入/輸出:LCD[4]/LCD[3]/LCD[8]/LCD[18] |
||
I/O |
MCIDAT2:SD/MMC接口數據線2 |
||
I/O |
I2STX_WS:I2S傳輸字選擇。 |
||
P2[13] |
102 |
I/O |
P2[13]:GPIO口 |
I/O |
EINT3:外部中斷3輸入/輸出:LCD[5]/LCD[9]/LCD[19] |
||
I/O |
MCIDAT3:SD/MMC接口數據線3 |
||
I/O |
I2STX_SDA:I2S傳輸數據。 |
||
P2[14] |
91 |
I/O |
P2[14]:GPIO口 |
O |
CS2:低電平有效片選信號2 |
||
I |
CAP2[0]:Tmer2捕獲輸入通道0 |
||
I/O |
SDA1:I2C1數據輸入/輸出 |
||
P2[15] |
99 |
I/O |
P2[15]:GPIO口 |
O |
CS3:低電平有效片選信號3 |
||
I |
CAP2[1]:Tmer2捕獲輸入通道1 |
||
I/O |
SCL1:I2C1時鐘輸入/輸出 |
||
P2[16] |
87 |
I/O |
P2[16]:GPIO口 |
O |
CAS:低電平有效SDRAM列地址選擇 |
||
P2[17] |
95 |
I/O |
P2[17]:GPIO口 |
O |
RAS:低電平有效SDRAM行地址選擇 |
||
P2[18] |
59 |
I/O |
P2[18]:GPIO口 |
O |
CLKOUT0:SDRAM時鐘0 |
||
P2[19] |
67 |
I/O |
P2[19]:GPIO口 |
O |
CLKOUT1:SDRAM時鐘1 |
||
P2[20] |
73 |
I/O |
P2[20]:GPIO口 |
O |
DYCS0:SDRAM片選信號0 |
||
P2[21] |
81 |
I/O |
P2[21]:GPIO口 |
O |
DYCS1:SDRAM片選信號1 |
||
P2[22] |
85 |
I/O |
P2[22]:GPIO口 |
O |
DYCS2:SDRAM片選信號2 |
||
I |
CAP3[0]:Timer3捕獲輸入通道0 |
||
I/O |
SCK0:SSP0串行時鐘 |
||
P2[23] |
64 |
I/O |
P2[23]:GPIO口 |
O |
DYCS3:SDRAM片選信號3 |
||
I |
CAP3[1]:Timer3捕獲輸入通道1 |
||
I/O |
SSEL0:SSP0從機選擇 |
||
P2[24] |
53 |
I/O |
P2[24]:GPIO口 |
O |
CKEOUT0:SDRAM時鐘使能信號0 |
||
P2[25] |
54 |
I/O |
P2[25]:GPIO口 |
O |
CKEOUT1:SDRAM時鐘使能信號1 |
||
P2[26] |
57 |
I/O |
P2[26]:GPIO口 |
O |
CKEOUT2:SDRAM時鐘使能信號2 |
||
O |
MAT3[0]:Tmer3匹配輸出通道0 |
||
I/O |
MISO0:SSP0主機輸入從機輸出 |
||
P2[27] |
47 |
I/O |
P2[27]:GPIO口 |
O |
CKEOUT3:SDRAM時鐘使能信號3 |
||
O |
MAT3[1]:Tmer3匹配輸出通道1 |
||
I/O |
MOSI0:SSP0主機輸出從機輸入 |
||
P2[28] |
49 |
I/O |
P2[28]:GPIO口 |
O |
DQMOUT0:用於SDRAM和靜態設備的數據掩碼0 |
||
P2[29] |
43 |
I/O |
P2[29]:GPIO口 |
O |
DQMOUT1:用於SDRAM和靜態設備的數據掩碼1 |
||
P2[30] |
31 |
I/O |
P2[30]:GPIO口 |
O |
DQMOUT2:用於SDRAM和靜態設備的數據掩碼2 |
||
O |
MAT3[2]:Tmer3匹配輸出通道2 |
||
I/O |
SDA2:I2C2數據輸入/輸出 |
||
P2[31] |
39 |
I/O |
P2[31]:GPIO口 |
O |
DQMOUT3:用於SDRAM和靜態設備的數據掩碼3 |
||
O |
MAT3[3]:Tmer3匹配輸出通道3 |
||
I/O |
SCL2:I2C2時鐘輸入/輸出 |
4. P3口: P3口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P3口管腳描述如表4.4所示。
表4.4 LPC2400的P3口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P3[0] |
197 |
I/O |
P3[0]:GPIO口 |
I/O |
D0:外部存儲器數據線0 |
||
P3[1] |
201 |
I/O |
P3[1]:GPIO口 |
I/O |
D1:外部存儲器數據線1 |
||
P3[2] |
207 |
I/O |
P3[2]:GPIO口 |
I/O |
D2:外部存儲器數據線2 |
||
P3[3] |
3 |
I/O |
P3[3]:GPIO口 |
I/O |
D3:外部存儲器數據線3 |
||
P3[4] |
13 |
I/O |
P3[4]:GPIO口 |
I/O |
D4:外部存儲器數據線4 |
||
P3[5] |
17 |
I/O |
P3[5]:GPIO口 |
I/O |
D5:外部存儲器數據線5 |
||
P3[6] |
23 |
I/O |
P3[6]:GPIO口 |
I/O |
D6:外部存儲器數據線6 |
||
P3[7] |
27 |
I/O |
P3[7]:GPIO口 |
I/O |
D7:外部存儲器數據線7 |
||
P3[8] |
191 |
I/O |
P3[8]:GPIO口 |
I/O |
D8:外部存儲器數據線8 |
||
P3[9] |
199 |
I/O |
P3[9]:GPIO口 |
I/O |
D9:外部存儲器數據線9 |
||
P3[10] |
205 |
I/O |
P3[10]:GPIO口 |
I/O |
D10:外部存儲器數據線10 |
||
P3[11] |
208 |
I/O |
P3[11]:GPIO口 |
I/O |
D11:外部存儲器數據線11 |
||
P3[12] |
1 |
I/O |
P3[12]:GPIO口 |
I/O |
D12:外部存儲器數據線12 |
||
P3[13] |
7 |
I/O |
P3[13]:GPIO口 |
I/O |
D13:外部存儲器數據線13 |
||
P3[14] |
21 |
I/O |
P3[14]:GPIO口 |
I/O |
D14:外部存儲器數據線14 |
||
P3[15] |
28 |
I/O |
P3[15]:GPIO口 |
I/O |
D15:外部存儲器數據線15 |
||
P3[16] |
137 |
I/O |
P3[16]:GPIO口 |
I/O |
D16:外部存儲器數據線16 |
||
O |
PWM0[1]:脈寬調製器0輸出1 |
||
O |
TXD1:UART1發送輸出端 |
||
P3[17] |
143 |
I/O |
P3[17]:GPIO口 |
I/O |
D17:外部存儲器數據線17 |
||
O |
PWM0[2]:脈寬調製器0輸出2 |
||
I |
RXD1:UART1接收輸入端 |
||
P3[18] |
151 |
I/O |
P3[18]:GPIO口 |
I/O |
D18:外部存儲器數據線18 |
||
O |
PWM0[3]:脈寬調製器0輸出3 |
||
I |
CTS1:UART1清除發送輸入端 |
||
P3[19] |
161 |
I/O |
P3[19]:GPIO口 |
I/O |
D19:外部存儲器數據線19 |
||
O |
PWM0[4]:脈寬調製器0輸出4 |
||
I |
DCD1:UART1數據載波檢測輸入端 |
||
P3[20] |
167 |
I/O |
P3[20]:GPIO口 |
I/O |
D20:外部存儲器數據線20 |
||
O |
PWM0[5]:脈寬調製器0輸出5 |
||
I |
DSR1:UART1數據設置就緒端 |
||
P3[21] |
175 |
I/O |
P3[21]:GPIO口 |
I/O |
D21:外部存儲器數據線21 |
||
O |
PWM0[6]:脈寬調製器0輸出6 |
||
O |
DTR1:UART1數據終端準備就緒輸出端 |
||
P3[22] |
195 |
I/O |
P3[22]:GPIO口 |
I/O |
D22:外部存儲器數據線22 |
||
I |
PCAP0[0]:脈寬調製器0捕獲輸入通道0 |
||
I |
RI1:UART1響鈴指示輸入端 |
||
P3[23] |
65 |
I/O |
P3[23]:GPIO口 |
I/O |
D23:外部存儲器數據線23 |
||
I |
CAP0[0]:Timer0捕獲輸入通道0 |
||
I |
PCAP1[0]:脈寬調製器1捕獲輸入通道0 |
||
P3[24] |
58 |
I/O |
P3[24]:GPIO口 |
I/O |
D24:外部存儲器數據線24 |
||
I |
CAP0[1]:Timer0捕獲輸入通道1 |
||
O |
PWM1[1]:脈寬調製器1輸出1 |
||
P3[25] |
56 |
I/O |
P3[25]:GPIO口 |
I/O |
D25:外部存儲器數據線25 |
||
O |
MAT0[0]:Tmer0匹配輸出通道0 |
||
O |
PWM1[2]:脈寬調製器1輸出2 |
||
P3[26] |
55 |
I/O |
P3[26]:GPIO口 |
I/O |
D26:外部存儲器數據線26 |
||
O |
MAT0[1]:Tmer0匹配輸出通道1 |
||
O |
PWM1[3]:脈寬調製器1輸出3 |
||
P3[27] |
203 |
I/O |
P3[27]:GPIO口 |
I/O |
D27:外部存儲器數據線27 |
||
I |
CAP1[0]:Timer1捕獲輸入通道0 |
||
O |
PWM1[4]:脈寬調製器1輸出4 |
||
P3[28] |
5 |
I/O |
P3[28]:GPIO口 |
I/O |
D28:外部存儲器數據線28 |
||
I |
CAP1[1]:Timer1捕獲輸入通道1 |
||
O |
PWM1[5]:脈寬調製器1輸出5 |
||
P3[29] |
11 |
I/O |
P3[29]:GPIO口 |
I/O |
D29:外部存儲器數據線29 |
||
O |
MAT1[0]:Tmer1匹配輸出通道0 |
||
O |
PWM1[6]:脈寬調製器1輸出6 |
||
P3[30] |
19 |
I/O |
P3[30]:GPIO口 |
I/O |
D30:外部存儲器數據線30 |
||
O |
MAT1[1]:Tmer1匹配輸出通道1 |
||
O |
RTS1:UART1請求發送輸出端 |
||
P3[31] |
25 |
I/O |
P3[31]:GPIO口 |
I/O |
D31:外部存儲器數據線31 |
||
O |
MAT1[2]:Tmer1匹配輸出通道2 |
5. P4口: P4口也是一個32位的雙向多功能I/O口,每位的方向可單獨控制,且每位的功能取決於管腳鏈接模塊的管腳功能選擇。LPC2400的P4口管腳描述如表4.5所示。
表4.5 LPC2400的P4口管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
P4[0] |
75 |
I/O |
P4[0]:GPIO口 |
I/O |
A0:外部存儲器地址線0 |
||
P4[1] |
79 |
I/O |
P4[1]:GPIO口 |
I/O |
A1:外部存儲器地址線1 |
||
P4[2] |
83 |
I/O |
P4[2]:GPIO口 |
I/O |
A2:外部存儲器地址線2 |
||
P4[3] |
97 |
I/O |
P4[3]:GPIO口 |
I/O |
A3:外部存儲器地址線3 |
||
P4[4] |
103 |
I/O |
P4[4]:GPIO口 |
I/O |
A4:外部存儲器地址線4 |
||
P4[5] |
107 |
I/O |
P4[5]:GPIO口 |
I/O |
A5:外部存儲器地址線5 |
||
P4[6] |
113 |
I/O |
P4[6]:GPIO口 |
I/O |
A6:外部存儲器地址線6 |
||
P4[7] |
121 |
I/O |
P4[7]:GPIO口 |
I/O |
A7:外部存儲器地址線7 |
||
P4[8] |
1271 |
I/O |
P4[8]:GPIO口 |
I/O |
A8:外部存儲器地址線8 |
||
P4[9] |
131 |
I/O |
P4[9]:GPIO口 |
I/O |
A9:外部存儲器地址線9 |
||
P4[10] |
135 |
I/O |
P4[10]:GPIO口 |
I/O |
A10:外部存儲器地址線10 |
||
P4[11] |
145 |
I/O |
P4[11]:GPIO口 |
I/O |
A11:外部存儲器地址線11 |
||
P4[12] |
149 |
I/O |
P4[12]:GPIO口 |
I/O |
A12:外部存儲器地址線12 |
||
P4[13] |
155 |
I/O |
P4[13]:GPIO口 |
I/O |
A13:外部存儲器地址線13 |
||
P4[14] |
159 |
I/O |
P4[14]:GPIO口 |
I/O |
A14:外部存儲器地址線14 |
||
P4[15] |
173 |
I/O |
P4[15]:GPIO口 |
I/O |
A15:外部存儲器地址線15 |
||
P4[16] |
101 |
I/O |
P4[16]:GPIO口 |
I/O |
A16:外部存儲器地址線16 |
||
P4[17] |
104 |
I/O |
P4[17]:GPIO口 |
I/O |
A17:外部存儲器地址線17 |
||
P4[18] |
105 |
I/O |
P4[18]:GPIO口 |
I/O |
A18:外部存儲器地址線18 |
||
P4[19] |
111 |
I/O |
P4[19]:GPIO口 |
I/O |
A19:外部存儲器地址線19 |
||
P4[20] |
109 |
I/O |
P4[20]:GPIO口 |
I/O |
A20:外部存儲器地址線20 |
||
I/O |
SDA2:I2C2數據輸入/輸出 |
||
I/O |
SCK1:SSP1串行時鐘 |
||
P4[21] |
115 |
I/O |
P4[21]:GPIO口 |
I/O |
A21:外部存儲器地址線21 |
||
I/O |
SCL2:I2C2時鐘輸入/輸出 |
||
I/O |
SSEL1:SSP1從機選擇 |
||
P4[22] |
123 |
I/O |
P4[22]:GPIO口 |
I/O |
A22:外部存儲器地址線22 |
||
O |
TXD2:UART2發送輸出端 |
||
I/O |
MISO1:SSP1主機輸入從機輸出 |
||
P4[23] |
129 |
I/O |
P4[23]:GPIO口 |
I/O |
A23:外部存儲器地址線23 |
||
I |
RXD2:UART2接收輸入端 |
||
I/O |
MOSI1:SSP1主機輸出從機輸入 |
||
P4[24] |
183 |
I/O |
P4[24]:GPIO口 |
O |
OE:低電平有效輸出使能信號 |
||
P4[25] |
179 |
I/O |
P4[25]:GPIO口 |
O |
WE:低電平有效寫使能信號 |
||
P4[26] |
119 |
I/O |
P4[26]:GPIO口 |
O |
BLS0:低電平有效字節定位選擇信號0 |
||
P4[27] |
139 |
I/O |
P4[27]:GPIO口 |
O |
BLS1:低電平有效字節定位選擇信號1 |
||
P4[28] |
170 |
I/O |
P4[28]:GPIO口 |
O |
BLS2:低電平有效字節定位選擇信號2 |
||
O |
MAT2[0]/LCD[6]/LCD[10]/LCD[2]:Timer2匹配輸出通道0/LCD數據 |
||
O |
TXD3:UART3發送輸出端 |
||
P4[29] |
176 |
I/O |
P4[29]:GPIO口 |
O |
BLS3:低電平有效字節定位選擇信號3 |
||
O |
MAT2[1]/LCD[7]/LCD[11]/LCD[3]:Timer2匹配輸出通道1/LCD數據 |
||
I |
RXD3:UART3接收輸入端 |
||
P4[30] |
187 |
I/O |
P4[30]:GPIO口 |
O |
CS0:低電平有效片選信號0 |
||
P4[31] |
193 |
I/O |
P4[31]:GPIO口 |
O |
CS1:低電平有效片選信號1 |
6. 電源、復位、晶振及其它管腳的描述如表4.6所示。
表4.6 LPC2400的其它管腳描述
管腳名稱 |
引腳號 |
類型 |
描 述 |
ALARM |
37 |
O |
RTC實時時鐘控制輸出。這是一個1.8V引腳,當RTC產生報警信號時此引腳變爲高電平。 |
USB_D-2 |
52 |
I/O |
USB端口2雙向D-線 |
DBGEN |
9 |
I |
JTAG接口控制信號,也用於邊界掃描 |
TDO |
2 |
O |
JTAG接口測試數據輸出 |
TDI |
4 |
I |
JTAG接口測試數據輸入 |
TMS |
6 |
I |
JTAG接口測試模式選擇 |
TRST |
8 |
I |
JTAG接口測試復位,低電平有效 |
TCK |
10 |
I |
JTAG接口測試時鐘 |
RTCK |
206 |
I/O |
JTAG接口控制信號,當此引腳低電平時使能ETM引腳(P2[9:0]),用於復位後操做跟蹤端口 |
RSTOUT |
29 |
O |
這是個1.8V引腳,當此引腳低電平時表示LPC2478處於復位狀態 |
RESET |
35 |
I |
外部復位輸入,低電平有效。該引腳具備遲滯做用的TTL電平,能承受5V電壓,當此引腳低電平時器件復位,I/O口和外圍功能進入默認狀態,處理器從地址0開始執行程序 |
XTAL1 |
44 |
I |
振盪器電路和內部時鐘發生電路輸入 |
XTAL2 |
46 |
O |
振盪放大器輸出 |
RTCX1 |
34 |
I |
RTC振盪器電路輸入 |
RTCX2 |
36 |
O |
RTC振盪器電路輸出 |
VSSIO |
33,63,77,93,114,133,148,169,189,200 |
I |
地:數字IO腳的0V電壓參考點 |
VSSCORE |
32,84,172 |
I |
地:處理器內核的0V電壓參考點 |
VSSA |
22 |
I |
模擬地:0V電壓參考點,與VSS電壓相同,爲了下降噪聲和出錯概率,二者應當隔離 |
VDD(3V3) |
15,60,71,89,112,125,146,165,181,198 |
I |
3.3V供應電壓:I/O口電源供應電壓 |
NC |
30,117,141 |
I |
未鏈接引腳 |
VDD(DCDC)(3V3) |
26,86,174 |
I |
3.3V直流到直流轉換供應電壓:爲片內DC-to-DC轉換器提供電源 |
VDDA |
20 |
I |
模擬3.3V供應電壓:爲DAC和ADC供電,與VDD(3V3)電壓相同,爲了下降噪聲和出錯概率,二者應當隔離 |
VREF |
24 |
I |
ADC參考電壓:與VDD(3V3)電壓相同,爲了下降噪聲和出錯概率,二者應當隔離,爲ADC和DAC提供參考電壓 |
VBAT |
38 |
I |
RTC電源供應:3.3V,爲RTC提供電源 |
注:1. 本引腳定義表以LPC2478爲準,LPC2470與此相同,LPC2468沒有引腳定義的LCD部分。
2. 類型表示引腳信號方向:I/O爲輸入/輸出,I爲輸入,O爲輸出。
從表4.1~表4.6能夠看到,LPC2400系列芯片的絕大部分引腳是複用的,每根引腳都有可能用於不一樣的外設功能。引腳具體用於什麼外設功能是由引腳鏈接模塊進行配置來實現的。當引腳選擇了一個功能時,則其它功能無效。
在使用外設時,應當在激活外設以及使能任何相關的中斷以前,將外設鏈接到相應的引腳上。不然,即便使用引腳鏈接模塊激活外設,此激活也是無效的。
引腳鏈接模塊共有21個寄存器,包括11個引腳功能選擇寄存器和10個引腳模式寄存器。
1. 引腳功能選擇寄存器(PINSEL0~PINSEL10)
引腳功能選擇寄存器用於控制每一個引腳的功能,每一個寄存器32位,每2個bit用於控制1個引腳功能選擇。以PINSEL0寄存器爲例,寄存器的[1:0]位用於控制P0[0]引腳,[3:2]位用於控制P0[1]引腳,[31:30]位用於控制P0[15]引腳。而PINSEL1寄存器的[1:0]位用於控制P0[16]引腳,[3:2]位用於控制P0[17]引腳,[31:30]位用於控制P0[31]引腳。其他依次類推。
PINSEL0~PINSEL9寄存器,每兩個寄存器用於一個端口組:PINSEL0寄存器用於P0口的[15:0]引腳,PINSEL1寄存器用於P0口的[31:30]引腳;PINSEL2寄存器用於P1口的[15:0]引腳,PINSEL3寄存器用於P1口的[31:30]引腳;PINSEL4寄存器用於P2口的[15:0]引腳,PINSEL5寄存器用於P2口的[31:30]引腳;PINSEL6寄存器用於P3口的[15:0]引腳,PINSEL7寄存器用於P3口的[31:30]引腳;PINSEL8寄存器用於P4口的[15:0]引腳,PINSEL9寄存器用於P4口的[31:30]引腳。
每一對比特設置引腳功能的定義如表4.7所示。
表4.7 引腳功能選擇寄存器位
PINSEL0~PINSEL9值 |
功能 |
復位值 |
00 |
主功能(缺省),通常爲GPIO口 |
00 |
01 |
第一備用功能 |
|
10 |
第二備用功能 |
|
11 |
第三備用功能 |
每一個引腳默認爲GPIO口,經過設置PINSEL的值來定義其引腳功能。以P0[0]腳爲例,當PINSEL0寄存器的[1:0]位爲00時,引腳功能爲GPIO口;爲01時,引腳功能爲CAN1接收器輸入;爲10時,引腳功能爲UART3發送輸出端;爲11時,引腳功能爲I2C1數據輸入/輸出。
每一個引腳的具體定義方法參見表4.1~表4.6。表格中的引腳功能按PINSEL值排列。某些引腳只有兩種功能,此時只使用PINSEL值00和01,值10和11保留。
PINSEL10寄存器用於控制ETM接口引腳。該寄存器只使用了位3,其他位均保留。當第3位爲0時,關閉ETM接口功能;爲1時啓用ETM跟蹤接口功能,此時不管PINSEL4怎麼定義,P2[0]~P2[8]腳均用於ETM跟蹤功能。
引腳功能被選擇爲GPIO時,引腳的方向控制由GPIO方向寄存器IODIR控制。對於其它功能,引腳的方向是由引腳功能控制的。
2. 引腳模式寄存器(PINMODE0~PINMODE9)
引腳模式寄存器PINMODE爲全部的GPIO端口控制片內上拉/下拉電阻特性。當使用片內上拉或下接電阻時,若引腳信號不肯定,使用上拉時爲高電平;而下拉時拉爲低電平。
與PNSEL寄存器同樣,PINMODE寄存器每2個bit控制1個引腳。每兩個寄存器控制一個端口組。
PINMOD寄存器取值如表4.8所示。
表4.8 引腳模式寄存器位
PINMODE0~PINMODE9值 |
功能 |
復位值 |
00 |
使能引腳片內上拉電阻 |
00 |
01 |
保留 |
|
10 |
既不使用上拉也不使用下拉 |
|
11 |
使能引腳片內下拉電阻 |
引腳鏈接模塊的寄存器總表如表4.9所示。
表4.9 引腳控制模塊寄存器列表
寄存器名 |
描述 |
訪問 |
復位值 |
地址 |
PINSEL0 |
引腳功能選擇寄存器0 |
讀/寫 |
0x0000 0000 |
0xE002 C000 |
PINSEL1 |
引腳功能選擇寄存器1 |
讀/寫 |
0x0000 0000 |
0xE002 C004 |
PINSEL2 |
引腳功能選擇寄存器2 |
讀/寫 |
0x0000 0000 |
0xE002 C008 |
PINSEL3 |
引腳功能選擇寄存器3 |
讀/寫 |
0x0000 0000 |
0xE00 |