版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、基于基于ARM的嵌入式系統(tǒng)應(yīng)用程序設(shè)的嵌入式系統(tǒng)應(yīng)用程序設(shè)計(jì)計(jì)第一節(jié)第一節(jié) 偽操作、宏指令與偽指令偽操作、宏指令與偽指令一、一、z 1. ADS/SDT IDE開發(fā)環(huán)境開發(fā)環(huán)境z ARM公司開發(fā),使用了CodeWarrior公司的編譯器; z 2. 集成了集成了GNU開發(fā)工具的開發(fā)工具的IDE開發(fā)環(huán)境開發(fā)環(huán)境z 它由GNUz 匯編器asz 交叉編譯器gccz 鏈接器ld等組成。二、二、z 常量編譯控制偽操作z 字符編譯控制偽操作z 匯編程序代碼控制偽操作z 宏及條件編譯控制偽操作z 其他偽操作偽操作語(yǔ)法格式作 用.byte.byte expr ,expr 分配一段字節(jié)內(nèi)存單元,并用expr初始
2、化。.hword/.short.hword expr ,expr 分配一段半字內(nèi)存單元,并用expr初始化。.ascii.ascii expr ,expr 定義字符串expr(非零結(jié)束符)。.asciz /.string.asciz expr ,expr 定義字符串expr(以/0為結(jié)束符)。.float/.single.float expr ,expr 定義一個(gè)32bit IEEE 浮點(diǎn)數(shù)expr。.double.double expr ,expr 定義64bit IEEE浮點(diǎn)數(shù)expr。word/.long /.int.word expr ,expr 分配一段字內(nèi)存單元,并用expr初始化
3、。.fill.fill repeat ,size,value分配一段字節(jié)內(nèi)存單元,用size長(zhǎng)度value填充repeat次。.zero.zero size分配一段字節(jié)內(nèi)存單元,并用0填充內(nèi)存。.space/.skip.space size , value分配一段內(nèi)存單元,用value將內(nèi)存單元初始化。z1.常量編譯控制偽操作常量編譯控制偽操作.byte 21,48,89,0 x13,0 xFF.hword 21,25,89,0 x1133,0 x77FF.ascii “How are you”.asciz “I am a atudent”.float 0F3.14,0F359.2E11.do
4、uble 0F2E1.word 21,0 x110033.fill 8,4,0 xFFFFFFFF.zero 400.space 10,0BFFz2.字符編譯控制偽操作字符編譯控制偽操作 .equ.set.equ symbol,expr.set symbol,expr為數(shù)字常量、基于寄存器的值和程序中的標(biāo)號(hào)(expr)定義一個(gè)字符名稱symbol。.global.globl.global symbol.globl symbol聲明一個(gè)符號(hào)(symbol)可被其他文件引用。偽操作語(yǔ)法格式作 用.extern.extern symbol 聲明一個(gè)符號(hào)可被其他文件引用。.equ num,20.equ
5、 PLLCON,0 x01D80000.extern Image_RO_Limit.global _start.global Func偽操作語(yǔ)法格式作 用.section.section expr定義域中包含的段。.text.text subsection將操作符開始的代碼編譯到代碼段或代碼段子段。.data.data subsection將操作符開始的數(shù)據(jù)編譯到數(shù)據(jù)段或數(shù)據(jù)段子段。.bss.bss subsection將變量存放到.bss段(為靜態(tài)和全局變量保留的可讀/寫的數(shù)據(jù)區(qū))或.bss段的子段。.code 16/.thumb.code 16.thumb表明當(dāng)前匯編指令的指令集選擇Thu
6、mb指令集。.code 32/.arm.code 32.arm表明當(dāng)前匯編指令的指令集選擇ARM指令集。.end.end標(biāo)記匯編文件的結(jié)束行,即標(biāo)號(hào)后的代碼不作處理。.include.include “filename”將一個(gè)源文件包含到當(dāng)前源文件中。.align/.balign.align alignment,fill ,max通過添加填充字節(jié)使當(dāng)前位置滿足一定的對(duì)齊方式。.align 4 /*字對(duì)齊*/z3.匯編程序代碼控制偽操作匯編程序代碼控制偽操作 .section .bss偽操作語(yǔ)法格式作 用.macro.exitm.endm.macro acroname p a r a m e t
7、 e r , parameter.endm.macro標(biāo)識(shí)宏定義的開始。.endm標(biāo)識(shí)宏定義的結(jié)束。用.macro及.endm定義一段代碼,稱為宏定義體。.exitm偽操作用于提前退出宏。.ifdef.else.endif.ifdef condition.else.endif 當(dāng)滿足某條件時(shí)對(duì)一組語(yǔ)句進(jìn)行編譯,而當(dāng)條件不滿足時(shí)則編譯另一組語(yǔ)句。其中else可以缺省。z4.宏及條件編譯控制偽操作宏及條件編譯控制偽操作 z例:例:宏操作。.macroHANDLER LabelSUBSP,SP,#4STMFDSP!,R0LDRR0,= LabelLDRR0,R0STRR0,SP,#4LDMFDSP!
8、,R0,PC.endm宏名HANDLER有一個(gè)參數(shù)Label宏定義體結(jié)束z例:例:宏操作。.macroHANDLER_irq LabelSTMDBSP!,R0-R11,IP,LRLDRR0,= LabelLDRR0,R0MOVLR,PCBXR0LDMIASP!,R0 -R11,IP,LRSUBSPC,R14,#4.endm宏名HANDLER_irq有一個(gè)參數(shù)Label宏定義體結(jié)束保存R0R11 IP(R12),LR把Label的地址加載到R0加載Label的內(nèi)容到R0調(diào)用用戶中斷處理程序恢復(fù)R0R11 IP(R12),LR中斷返回z例:例:宏退出。.macroHANDLER LabelSUBS
9、P,SP,#4STMFDSP!,R0LDRR0,= Label.exitmLDRR0,R0STRR0,SP,#4LDMFDSP!,R0.endm宏名HANDLER,有一個(gè)參數(shù)Label宏定義體結(jié)束提前退出宏z例:例:條件編譯偽操作。.ifdef PLLONSTARTLDR R0,=PLLCONLDR R1,=(M_DIV12)+(P_DIV4)+S_DIV)STR R1,R0.endif偽操作語(yǔ)法格式作 用.eject.eject在匯編符號(hào)列表文件中插入一分頁(yè)符。.list.list產(chǎn)生匯編列表(從 .list 到 .nolist)。.nolist.nolist表示匯編列表結(jié)束處。.title
10、.title “heading”使用“heading ”作為標(biāo)題.sbttl.sbttl “heading”使用“heading”作為子標(biāo)題。.ltorg.ltorg在當(dāng)前段的當(dāng)前地址(字對(duì)齊)產(chǎn)生一個(gè)文字池。一般放在跳轉(zhuǎn)指令后面。.req.req name,expr為一個(gè)特定的寄存器定義名稱。.err.err使編譯時(shí)產(chǎn)生錯(cuò)誤報(bào)告。.print.print string打印信息到標(biāo)準(zhǔn)輸出。.fail.fail expr編譯匯編文件時(shí)產(chǎn)生警告。z5.其他偽操作其他偽操作 .title “My Asm Output”.sbttl “Part1:Cool stuff”.req COUNT,7 /*定
11、義寄存器7為COUNT*/第一節(jié)第一節(jié) 偽操作、宏指令與偽指令偽操作、宏指令與偽指令偽指令語(yǔ)法格式作 用ADRADR cond register,expr將基于PC或寄存器的地址值讀取到寄存器中。小范圍的地址讀取。ADRLADRLcondregister,expr將基于PC或寄存器的地址值讀取到寄存器中。中等范圍的地址讀取。LDRLDRcond register,=expr|label-expr將一個(gè)32位立即數(shù)或一個(gè)地址值讀取到寄存器中。大范圍地址讀取。NOPNOP匯編時(shí)被替換成ARM中的空操作。三、三、z ARM中偽指令不是真正的ARM或Thumb指令,它們?cè)诰幾g器對(duì)源程序進(jìn)行匯編處理時(shí)被
12、替換成相應(yīng)的ARM或Thumb指令序列。z1. 小范圍的地址讀取偽指令小范圍的地址讀取偽指令A(yù)DRz ADR cond register,exprz cond:可選的執(zhí)行條件z register:目標(biāo)寄存器z expr:基于PC或寄存器的地址表達(dá)式z使用說明使用說明:z 通常被編譯器替換成一條ADD或SUB指令來實(shí)現(xiàn)該ADR的功能。被編譯替換成SUB R1,PC,#0 xc因PC值為當(dāng)前指令地址加8。z例:例:start MOVR0,#10 ADRR1,startz2. 中范圍的地址讀取偽指令中范圍的地址讀取偽指令A(yù)DRLz ADRL cond register,exprz使用說明使用說明:z
13、 通常被編譯器替換成2條合適的數(shù)據(jù)處理指令來實(shí)現(xiàn)該ADRL的功能。z例:例:startMOVR0,#10ADRLR4,start+60000z本ADRL替換成:ADDR4,PC,#84ADDR4,R4,#59904因PC值為當(dāng)前指令地址加8。R4PC-0 xc+60000z3. 大范圍的地址讀取偽指令大范圍的地址讀取偽指令LDRz LDR cond register,=exprlabel-exprz expr:32位常量z label-expr:基于PC的地址表達(dá)式或外部表達(dá)式z使用說明使用說明:z (1) 讀取的數(shù)據(jù)超過了MOV及MVN指令可操作的范圍時(shí),用LDR讀數(shù)據(jù)到寄存器。z (2)
14、將一個(gè)基于PC的地址值或外部的地址值讀到寄存器。z LDR用于裝載大常數(shù),或從數(shù)據(jù)池讀取常數(shù)。z例:例:LDR R1,=0 xFFz 匯編后將得到: LDRR1,#0 xFFz例:例:LDRR1,=0 x55555555z 匯編后將得到:LDR R1,PC ,#Imm12DCD 0 x5555555510第四章第四章 基于基于ARM的嵌入式系統(tǒng)應(yīng)用程序設(shè)的嵌入式系統(tǒng)應(yīng)用程序設(shè)計(jì)計(jì)第二節(jié)第二節(jié) ARM ARM 匯編語(yǔ)言程序設(shè)計(jì)匯編語(yǔ)言程序設(shè)計(jì)一、一、z 常用的源文件可簡(jiǎn)單分為以下幾種:z (1) *.S 匯編程序文件z (2) *.C C程序文件z (3) *.H 頭文件,把程序中常用到的常量命
15、名、宏定義、數(shù)據(jù)結(jié)構(gòu)定義等等單獨(dú)放在一個(gè)文件中,一般稱為頭文件。二、二、z ARM匯編語(yǔ)言語(yǔ)句格式如下所示: symbolinstruction | directive | pseudo-instruction ;commentz symbol 符號(hào) z instruction 指令 z directive 偽操作 z pseudo-instruction 偽指令 z comment 語(yǔ)句的注釋三、三、z ARM匯編語(yǔ)言是以段(section)為單位來組織源文件的。段是相對(duì)獨(dú)立的、具有特定名稱的、不可分割的指令或者數(shù)據(jù)序列。z 段又可以分為代碼段和數(shù)據(jù)段。z 一個(gè)ARM源程序至少需要一個(gè)代碼段
16、。 z例:ARM匯編語(yǔ)言源程序的基本結(jié)構(gòu) .global _start .text _start: MOV R0,#10 MOV R1,#3 ADD R0,r0,r1 .end定義全局標(biāo)號(hào)標(biāo)志代碼段默認(rèn)入口點(diǎn)結(jié)束標(biāo)志四、四、z1. ARM數(shù)據(jù)處理操作數(shù)據(jù)處理操作z(1) 簡(jiǎn)單的寄存器操作簡(jiǎn)單的寄存器操作 ADD R0, R1, R2 ;R0 = R1 + R2z(2) 立即數(shù)操作立即數(shù)操作 ADD R3, R3,#1 ;R3 = R3 + 1 AND R8, R7,#0 xFF ;R8 = R77:0z 有效立即數(shù)是由一個(gè)8位的立即數(shù)循環(huán)右移2n位得到。z(3) 寄存器移位操作寄存器移位操作
17、ADD R3, R2,R1,LSL #3 ;R3r2)r0=r1-r2;elser0=r2-r1;z記住ARM只有一個(gè)CPSRCMP r1,r2SUBGTr0,r1,r2SUBLT r0,r2,r1if(r1r2 | r1r3)r0=r1-r2;CMP r1,r2CMPLTr1,r3SUBGT r0,r1,r2if(r1r2 & r1r3)r0=r1-r2;CMP r1,r2CMPGTr1,r3SUBGT r0,r1,r2z4. 復(fù)雜的分支結(jié)構(gòu)復(fù)雜的分支結(jié)構(gòu)if(r1r2)r0=r1-r2; if(r0r3)r0=1;elser0=0;elser0=r2-r1;if(r0r3)r0=1;els
18、er0=0;z ARM只有一個(gè)CPSR,而本例有兩個(gè)判斷的嵌套:如果按照高級(jí)語(yǔ)言的流程在第二個(gè)條件判斷if(r0r3)后,CPSR的值就不適合用在else部分了。z解決方法解決方法:z (1) 使用跳轉(zhuǎn)語(yǔ)句。z (2) 使用跳轉(zhuǎn)表。z (3) 直接對(duì)CPSR進(jìn)行操作。z (4) 使用邏輯表達(dá)式,記錄邏輯結(jié)構(gòu)的狀態(tài)。if(r1r2)r0=r1-r2; if(r0r3)r0=1;elser0=0;elser0=r2-r1;if(r0r3)r0=1;elser0=0;z(1) 使用跳轉(zhuǎn)語(yǔ)句使用跳轉(zhuǎn)語(yǔ)句 使用帶條件的“B”指令BEGIF CMP r1,r2 BLEELSE SUB r0,r1,r2 C
19、MPGT r0,r3 MOVGT r0,#1 MOVLE r0,#0 BENDIFELSE SUB r0,r2,r1 CMPGT r0,r3 MOVGT r0,#1 MOVLE r0,#0ENDIFz跳轉(zhuǎn)指令會(huì)影響流水線的執(zhí)行if(r1r2)r0=r1-r2; if(r0r3)r0=1;elser0=0;elser0=r2-r1;if(r0r3)r0=1;elser0=0;z(2) 采用方法采用方法(3)對(duì)對(duì)CPSR操作操作 CMP r1,r2 MSRLEr5,CPSR SUBGT r0,r1,r2 CMPGT r0,r3 MOVGT r0,#1 MOVLE r0,#0ELSE MSRCPSR
20、_f,r5 SUBLE r0,r2,r1 CMP r0,r3 MOVGT r0,#1 MOVLE r0,#0z如果每個(gè)if分支都有大量計(jì)算任務(wù),則應(yīng)用跳轉(zhuǎn)方法。if(r1r2)r0=r1-r2; if(r0r3)r0=1;elser0=0;elser0=r2-r1;if(r0r3)r0=1;elser0=0;z(3)采用方法采用方法(4) 使用臨時(shí)變量保存寄存器的值 CMP r1,r2 MOVLEr5,#1 SUBGT r0,r1,r2 CMPGT r0,r3 MOVGT r0,#1 MOVLE r0,#0ELSE CMPr5,#1 SUBEQ r0,r2,r1 CMPEQ r0,r3 MOV
21、GT r0,#1 MOVLE r0,#0z將r1r2(1)的狀態(tài)保存在r5z5. 利用跳轉(zhuǎn)表實(shí)現(xiàn)程序跳轉(zhuǎn)利用跳轉(zhuǎn)表實(shí)現(xiàn)程序跳轉(zhuǎn).global _start.text.equNUM2_startMOVR0,#0MOVR1,#3MOVR2,#2BLFuncStopMOVR0,#0 x18LDRR1,=0 x20026SWI0X123456FuncCMPR0,#NUMMOVHS PC,LRADRR3,JTableLDRPC,R3,R0,LSL#2Jtable.longDoAdd.longDoSubDoAdd ADDR0,R1,R2MOVPC,LRDoSub SUB R0,R1,R2MOVPC,LR.
22、end跳轉(zhuǎn)表中放子程序的入口地址,R3放跳轉(zhuǎn)表基地址,R0用于選擇不同子程序。跳轉(zhuǎn)表中子程序個(gè)數(shù)R1R2是子程序用的參數(shù)返回調(diào)試器調(diào)用子程序FuncR0超出范圍返回R3放跳轉(zhuǎn)表基地址加R0*4送PC跳轉(zhuǎn)表加法子程序減法子程序11第四章第四章 基于基于ARM的嵌入式系統(tǒng)應(yīng)用程序設(shè)的嵌入式系統(tǒng)應(yīng)用程序設(shè)計(jì)計(jì)第三節(jié)第三節(jié) 嵌入式嵌入式C C語(yǔ)言程序設(shè)計(jì)語(yǔ)言程序設(shè)計(jì)一、一、z1. 條件語(yǔ)句條件語(yǔ)句z 格式:z(1) 兩重選擇兩重選擇 if (條件表達(dá)式) 語(yǔ)句1; else 語(yǔ)句2;z (2) 多重選擇多重選擇 if (條件表達(dá)式1) 語(yǔ)句2; else if(條件表達(dá)式2) 語(yǔ)句3; else if
23、(條件表達(dá)式n) 語(yǔ)句n;z例:例: 控制LED亮滅的條件語(yǔ)句void Led_Display(int LedStatus) led_state = LedStatus; if (LedStatus&0 x01)=0 x01) rPDATB=rPDATB&0 x5ff; else rPDATB=rPDATB|0 x200; if(LedStatus&0 x02)=0 x02) rPDATB=rPDATB&0 x3ff; else rPDATB=rPDATB|0 x400; led1亮led1滅led2滅led2亮z2. switch語(yǔ)句語(yǔ)句z 格式格式: switch(開關(guān)表達(dá)式) case常
24、量表達(dá)式1: 語(yǔ)句1; case常量表達(dá)式2: 語(yǔ)句2; case常量表達(dá)式n: 語(yǔ)句n; default: 語(yǔ)句n+1; z例:例:利用switch來選擇不同功能模塊的測(cè)試。void user_input_action(int value) if(!(value 0 x39) Uart_Printf(%x,value-0 x30); switch(value) case 0:TS_Test(); break; case 1:Digit_Led_Test();break;default:break; 如果用戶輸入0,則進(jìn)行觸摸屏的測(cè)試輸入“1”則進(jìn)行8段數(shù)碼管測(cè)試z3. 循環(huán)語(yǔ)句循環(huán)語(yǔ)句z (
25、1) for循環(huán)語(yǔ)句循環(huán)語(yǔ)句z 格式: for(表達(dá)式1;表達(dá)式2;表達(dá)式3) 語(yǔ)句; z例:例:控制在8段數(shù)碼管中循環(huán)顯示0Fvoid Digit_Led_Test(void)int i;for( i=16; i0; i-) Digit_Led_Symbol(i); Delay(4000); 循環(huán)顯示 F 0z (2) while循環(huán)語(yǔ)句循環(huán)語(yǔ)句z 格式: while(條件表達(dá)式) 語(yǔ)句;z (3) do while循環(huán)語(yǔ)句循環(huán)語(yǔ)句z 格式: do 語(yǔ)句; while(條件表達(dá)式);第三節(jié)第三節(jié) 嵌入式嵌入式C C語(yǔ)言程序設(shè)計(jì)語(yǔ)言程序設(shè)計(jì)二、二、z 以S3VCE40開發(fā)板上各個(gè)功能模塊的整個(gè)
26、測(cè)試程序?yàn)槔榻B運(yùn)用C語(yǔ)言進(jìn)行基于ARM的嵌入式程序設(shè)計(jì)。z S3VCE40開發(fā)板加電,數(shù)碼管全亮,LED1、LED2輪流閃爍,串口終端顯示信息。 1L o o k a t 8 - s e g me n t Di g i t L E D. . . 八段數(shù)碼管顯示0 F 后退出 2L o o k a t L C D. . . L C D顯示規(guī)則圖形 3P l e a s e p r e s s o n e k e y o nK e y B o a d ( 4 x 4 ) a n d l o o k a t L E D . . . 按下實(shí)驗(yàn)板鍵盤后在數(shù)碼管顯示鍵值 4C O DE C : P h
27、 i l i p s U DA1 3 4 1 ( U5 )P l e a s e l i s t e n t o s o u n d . P r e s s a n y k e y t o e x i t . . . 不斷輸出” 嘀嘀”聲 5T i me r S t a r t , p r e s s a n y k e y t o e x i t . . .* * * * 每秒打印一個(gè)符號(hào)* 6Wa i t i n g DH C P s e r v e r t o R e s p o n d .P r e s s a n y k e y t o e x i t . . . 偵聽網(wǎng)絡(luò)中的DH
28、C P s e r v e rR e c e i v e DH C P Me s s a g e f r o m s e r v e r 1 2 . 1 2 . 1 0 . 1C o n f i gl o c a li pa d d r e s s 1 2 . 1 2 . 1 0 . 5 返回所配置的I P 地址 7S S T 3 9 VF 1 6 0 - 9 0 ( U1 2 )Wr i t e 0 x 0 0 0 - 0 x f f t o f l a s h a d d r e s s 0 x 3 0 0 0 0 . . . F l a s h Wr i t e a n d C h e
29、c kS u c c e s s ! 對(duì)F L AS H 寫入再讀出并輸出比較結(jié)果 8I I C T e s t u s i n g AT 2 4 C 0 4 ( U1 8 ) . . .Wr i t e c h a r 0 - f i n t o AT 2 4 C 0 4R e a d 1 6 b y t e s f r o m A T 2 4 C 0 4 0 1 2 3 4 5 6 7 8 9 a b c d e f 對(duì)E E P R OM寫入再讀出并輸出比較結(jié)果 9 DOS 配置靜態(tài)I PDo y o u wa n t t o c o n f i g u r e l o c a l I
30、P ?a r p s 1 9 2 . 1 6 8 . 0 . 1 0 0 0 - 0 6 - 9 8 - 0 1 - 7 e - 8 fY / y t o c o n f i g u r e l o c a l I Pa d d r ; D/ d t o u s e De f a u l t I Pa d d r ( 1 9 2 . 1 6 8 . 0 . 2 0 0 ) .P r e s s a n y k e y t o c o n t i n u e . . . ( y ) P l e a s e i n p u t I P a d d r e s s ( x x x . x x x .
31、 x x x . x x x ) t h e n p r e s s E NT E R : 按下Y或y 重新設(shè)置I P1 9 2 . 1 6 8 . 0 . 1 0 輸入合法的I P 地址Ma n u a l S e t l o c a li p1 9 2 . 1 6 8 . 0 . 1 0P r e s s a n y k e y t o e x i t . . . 運(yùn)行T F T P Do wn . e x e 軟件進(jìn)行測(cè)試 0T o u c h S c r e e n c o o r d i n a t e R a n g i n :( Xmi n , Y mi n ) i s : (
32、x x x , x x x ) ( X ma x , Yma x ) i s : ( x x x , x x x ) L C D顯示1 6 小格觸摸后串口輸出所在坐標(biāo)值T o u s e c u r r e n t s e t t i n g s . P r e s s N/ n k e y . Wa n t t o S e t Ag a i n ( Y/ N) ? Y或y按下后再觸摸顯示屏的任意對(duì)角進(jìn)行坐標(biāo)定位T o u c h T S P sC o r n o rt o e n s u r eXma x , Yma x , Xma x , Xmi nUs e r t o u c h c o
33、 o r d i n a t e ( X, Y) i s : ( 0 2 3 9 , 0 6 7 9 ) 第一個(gè)頂角坐標(biāo)U s e r t o u c h c o o r d i n a t e ( X, Y) i s : ( 0 6 0 8 , 0 3 0 3 ) 第二個(gè)頂角坐標(biāo)T o u c h S c r e e n c o o r d i n a t e R a n g i n :( Xmi n , Y mi n ) i s : ( 0 2 3 9 , 0 3 0 3 ) ( x 1 , y 1 ) ( Xma x , Y ma x ) i s : ( 0 6 0 8 , 0 6 7
34、9 ) ( x 2 , y 2 )T o u s e c u r r e n t s e t t i n g s . P r e s s N/ n k e y . Wa n t t o S e t Ag a i n ( Y/ N) ?N或n 按下后用戶可以觸摸顯示屏輸出所在坐標(biāo)值* 如果定位范圍誤差過大,按下Y或y重新定位即可,正常x 2 - x 1略大于3 2 0;y 2 - y 1略大于2 4 0P i x e l : 3 2 0 X 2 4 0 . C o o r d i n a t e R a n g i n : ( 0 , 0 ) -( 3 2 0 , 2 4 0 ) L C D T
35、 o u c h S c r e e nT e s t E x a mp l e ( p l e a s e t o u c h L C D s c r e e n )p r e s s a n y k e y t o e x i t . . . X- P o s i o n AI N1 i s 0 0 9 7 Y- P o s i o n AI N0 i s 0 1 3 2 X - P o s i o n A I N1 i s 0 1 1 7 Y - P o s i o n A I N0 i s 0 1 3 2z PC按鍵可選擇測(cè)試。z1.程序源代碼介紹程序源代碼介紹z 整個(gè)測(cè)試程序主文件m
36、ain.c的代碼構(gòu)成圖如下圖所示,由BootLoader啟動(dòng)程序進(jìn)入C語(yǔ)言主函數(shù)main()入口。z2. 嵌入式嵌入式C語(yǔ)言程序編寫的簡(jiǎn)單構(gòu)架語(yǔ)言程序編寫的簡(jiǎn)單構(gòu)架z(1) 需要用 #include 指令將本文件所用到的頭文件包含到該程序中;z 44blib.h:對(duì)程序開發(fā)中的函數(shù)進(jìn)行說明,并用宏定義對(duì)一些常用的表達(dá)式或常量進(jìn)行了預(yù)定義;z 44b.h:用宏的方式定義了程序中所需的44B0X片上涉及各模塊中寄存器的宏定義地址;z/*z* File:44BLIB.Hz * Desc:Samsung 44B0X CPU function declare and common definez*/z#
37、ifndef _44BLIB_H_z #define _44BLIB_H_z z #ifdef _cplusplusz extern C z #endifz/常量常量 z#define DebugOut Uart_Printfz z#define min(x1,x2) (x1x2)? x1:x2)z z#define ONESEC0 (62500)/16us resolution, max 1.04 secz#define ONESEC1 (31250)/32us resolution, max 2.09 secz#define ONESEC2 (15625)/64us resolution,
38、 max 4.19 secz#define ONESEC3 (7812)/128us resolution, max 8.38 secz#define ONESEC4 (MCLK/128/(0 xff+1) /60Mhz, 128*4us resolution, max 32.53 secz#define NULL 0z#define EnterPWDN(clkcon) (void (*)(int)0 xe0)(clkcon)z #define DOWNLOAD_ADDRESS _RAM_STARTADDRESSz /* 8led control register address */z #d
39、efine LED8ADDR (*(volatile unsigned char *)(0 x2140000)z#define LCD0 xFFz#define UART0 xFEz/ /* *對(duì)開發(fā)中用到的一些庫(kù)函數(shù)作函數(shù)原型定義對(duì)開發(fā)中用到的一些庫(kù)函數(shù)作函數(shù)原型定義* */ / zvoid Delay(int time); /Watchdog Timer is used.zvoid DelayMs(int ms_time);zvoid *malloc(unsigned nbyte); zvoid free(void *pt);zvoid Port_Init(void);zvoid Cach
40、e_Flush(void);zvoid ChangeMemCon(unsigned *pMemCfg);zvoid Uart_Select(int ch);zvoid Uart_TxEmpty(int ch);zvoid Uart_Init(int mclk,int baud);zchar Uart_Getch(void);zchar Uart_GetKey(void); zint Uart_GetIntNum(void);zvoid Uart_SendByte(int data);zvoid Uart_Printf(char *fmt,.);zvoid Uart_SendString(cha
41、r *pt);zvoid Timer_Start(int divider); /Watchdog Timer is used.zint Timer_Stop(void); /Watchdog Timer is used.zvoid Led_Display(int LedStatus);zvoid Beep(int BeepStatus);zvoid ChangePllValue(int m,int p,int s);z#ifdef _cpluspluszz#endifz#endif /* _44BLIB_H_ */ z44b.h:用宏的方式定義了程序中所需的44B0X片上涉及各模塊中寄存器的宏
42、定義地址;z#ifndef _44B0X_H_z #define _44B0X_H_z z #ifdef _cplusplusz extern C z #endifz z #include option.h z/*定義了44b0的系統(tǒng)配置寄存器地址*/ z #define rSYSCFG(*(volatile unsigned *)0 x1c00000)z /*定義了44b0中2個(gè)不可作Cache存儲(chǔ)區(qū)的起始與結(jié)束地址的寄存器的地址*/ z #define rNCACHBE0(*(volatile unsigned *)0 x1c00004) z #define rNCACHBE1(*(vol
43、atile unsigned *)0 x1c00008) z /*定義了44b0中存儲(chǔ)總線控制器的優(yōu)先級(jí)的寄存器地址*/ z #define rSBUSCON(*(volatile unsigned *)0 x1c40000) z /*定義了44b0中與存儲(chǔ)器相關(guān)的寄存器地址*/ z /*定義了44b0中與UART 相關(guān)的寄存器地址*/ z /*定義了44b0中與同步I/O口相關(guān)的寄存器地址*/ z /*定義了44b0中與音頻播放器IIS相關(guān)的寄存器地址*/ z(2) 需要將本文件中定義的函數(shù)進(jìn)行函數(shù)聲明;z(3) 定義本文件中用到的各種類型的外部變量及數(shù)組;z(4) 編寫各個(gè)函數(shù)代碼,其中包
44、括一個(gè)主函數(shù) main (),由 main () 提供主線,通過調(diào)用各子函數(shù)來實(shí)現(xiàn)各種功能。第四章第四章 基于基于ARM的嵌入式系統(tǒng)應(yīng)用程序設(shè)的嵌入式系統(tǒng)應(yīng)用程序設(shè)計(jì)計(jì)第四節(jié)第四節(jié) C與匯編語(yǔ)言混合編程與匯編語(yǔ)言混合編程z z1. C與匯編語(yǔ)言能很容易的混合與匯編語(yǔ)言能很容易的混合z(1)可實(shí)現(xiàn)C中無(wú)法實(shí)現(xiàn)的處理器功能z(2)使用性的或不支持的指令z(3)產(chǎn)生更高效的代碼z2. 直接鏈接變量和程序直接鏈接變量和程序z(1)確定符合程序調(diào)用規(guī)范ATPCSz(2)輸入/輸出相關(guān)的符號(hào)z3. 編譯器也可保留內(nèi)嵌匯編編譯器也可保留內(nèi)嵌匯編z(1)大多數(shù)arm指令級(jí)都可實(shí)現(xiàn)z(2)寄存器操作數(shù)可支持任意
45、的C的表達(dá)式z(3)內(nèi)嵌匯編代碼可由編譯器的優(yōu)化器來傳遞z ATPCS(ARM-Thumb Produce Call Standard)z 是ARM程序和Thumb程序中子程序調(diào)用的基本規(guī)則。z 這些基本規(guī)則包括子程序調(diào)用過程中寄存器的使用規(guī)則、數(shù)據(jù)棧的使用規(guī)則和參數(shù)的傳遞規(guī)則。z1. 寄存器的使用規(guī)則寄存器的使用規(guī)則z(1) 子程序間通過寄存器子程序間通過寄存器R0R3來傳遞來傳遞參數(shù)參數(shù)z 這時(shí),寄存器R0R3可以記作A1A4。z(2) 在子程序中,使用寄存器在子程序中,使用寄存器R4R11來保存局部變量來保存局部變量z 這時(shí),寄存器 R4R11可以記作V1V8。在Thumb程序中,通常只
46、能使用寄存器R4R7來保存局部變量 。z(3) 寄存器寄存器R12用作子程序間的用作子程序間的scratch寄存器寄存器z 用于保存SP,在函數(shù)返回時(shí)使用該寄存器出棧,記作ip。z(4) 寄存器寄存器R13用作數(shù)據(jù)棧指針用作數(shù)據(jù)棧指針z 記作sp z(5) 寄存器寄存器R14稱為鏈接寄存器稱為鏈接寄存器z 記作lrz(6) 寄存器寄存器R15是程序計(jì)數(shù)器是程序計(jì)數(shù)器z 記作pc 寄存器別名特殊名使用規(guī)則R0A1 參數(shù)/結(jié)果scratch寄存器1R1A2 參數(shù)/結(jié)果scratch寄存器2R2A3 參數(shù)/結(jié)果scratch寄存器3R3A4 參數(shù)/結(jié)果scratch寄存器4R4V1 ARM狀態(tài)局部變
47、量寄存器1R5V2 ARM狀態(tài)局部變量寄存器2R6V3 ARM狀態(tài)局部變量寄存器3R7V4WRARM狀態(tài)局部變量寄存器4,Thumb狀態(tài)工作寄存器R8V5 ARM狀態(tài)局部變量寄存器5R9V6SBARM狀態(tài)局部變量寄存器6,在支持RWPI的ATPCS中為靜態(tài)基址寄存器R10V7SLARM狀態(tài)局部變量寄存器7,在支持?jǐn)?shù)據(jù)棧檢查的ATPCS中為數(shù)據(jù)棧限制指針R11V8FPARM狀態(tài)局部變量寄存器8/幀指針R12 IP子程序內(nèi)部調(diào)用的scratch寄存器R13 SP數(shù)據(jù)棧指針R14 LR連接寄存器R15 PC程序計(jì)數(shù)器z2. 數(shù)據(jù)棧的使用規(guī)則數(shù)據(jù)棧的使用規(guī)則z ATPCS規(guī)定數(shù)據(jù)棧為數(shù)據(jù)棧為FD(滿遞
48、減滿遞減)類型類型,并且對(duì)數(shù)據(jù)棧的操作是8字節(jié)對(duì)齊的。z3. 參數(shù)的傳遞規(guī)則參數(shù)的傳遞規(guī)則z(1)參數(shù)個(gè)數(shù)固定的子程序參數(shù)傳遞規(guī)則參數(shù)個(gè)數(shù)固定的子程序參數(shù)傳遞規(guī)則z 第一個(gè)整數(shù)參數(shù),通過寄存器R0R3來傳遞。其他參數(shù)通過數(shù)據(jù)棧傳遞。 z(2)參數(shù)個(gè)數(shù)可變的子程序參數(shù)傳遞規(guī)則參數(shù)個(gè)數(shù)可變的子程序參數(shù)傳遞規(guī)則z 當(dāng)參數(shù)不超過4個(gè)時(shí),可以使用寄存器R0R3來傳遞參數(shù);z 當(dāng)參數(shù)超過4個(gè)時(shí),還可以使用數(shù)據(jù)棧來傳遞參數(shù)。z(3) 子程序結(jié)果返回規(guī)則子程序結(jié)果返回規(guī)則 z 結(jié)果為一個(gè)32位的整數(shù)時(shí),可通過寄存器R0返回;z 結(jié)果為一個(gè)64位整數(shù)時(shí),可以通過寄存器R0和R1返回,依次類推。第四節(jié)第四節(jié) C與
49、匯編語(yǔ)言混合編程與匯編語(yǔ)言混合編程z z z 在C程序中嵌入?yún)R編程序可以實(shí)現(xiàn)一些高級(jí)語(yǔ)言沒有的功能,并可以提高執(zhí)行效率。armcc和armcpp內(nèi)嵌匯編器支持完整的ARM指令集;tcc和tcpp用于Thumb指令集。z 內(nèi)嵌的匯編指令包括大部分的ARM指令和Thumb指令,但是不能直接引用C的變量定義,數(shù)據(jù)交換必須通過ATPCS進(jìn)行。 z1. 內(nèi)嵌匯編指令的語(yǔ)法格式內(nèi)嵌匯編指令的語(yǔ)法格式 _asm(“指令;指令”);z ARM C匯編器使用關(guān)鍵字“_asm。如果有多條匯編指令需要嵌入,可以用“”將它們歸為一條語(yǔ)句。如: _asm 指令;指令 指令 z 注意:注意:_asm是兩個(gè)下劃線是兩個(gè)下劃
50、線。z2. 內(nèi)嵌匯編指令的特點(diǎn)內(nèi)嵌匯編指令的特點(diǎn)z(1) 操作數(shù)可以是寄存器、常量或C表達(dá)式。它們可以是char、short或者int類型,而且是作為無(wú)符號(hào)數(shù)進(jìn)行操作 。z(2) 內(nèi)嵌的匯編指令中使用物理寄存器有一些限制。z(3) 常量前的符號(hào)“#”可以省略。z(4) 只有指令B可以使用C程序中的標(biāo)號(hào),指令BL不能使用C程序中的標(biāo)號(hào)。z(5) 不支持匯編語(yǔ)言中用于內(nèi)存分配的偽操作。z(6) 指令中如果包含常量操作數(shù),該指令可能會(huì)被匯編器展開成幾條指令。z3. 內(nèi)嵌匯編注意事項(xiàng)內(nèi)嵌匯編注意事項(xiàng) z(1) 必須小心使用物理寄存器必須小心使用物理寄存器z 如R0R3,LR和PC。_asm MOVR0
51、,x ADDy,R0,x/yz 當(dāng)計(jì)算x/y時(shí),R0會(huì)被修改。用C語(yǔ)言的一個(gè)變量代替R0。_asm MOV var,x ADD y,var,x/yz(2) 不要使用寄存器尋址變量不要使用寄存器尋址變量int bad_f(int x) _asm ADDR0,R0,#1 return x;z 似乎R0對(duì)應(yīng)參數(shù)x,匯編器認(rèn)為寄存器沖突int bad_f(int x) _asm ADDx,x,#1 return x;z(3) 使用內(nèi)嵌匯編時(shí),編譯器自己會(huì)保使用內(nèi)嵌匯編時(shí),編譯器自己會(huì)保存和恢復(fù)它可能用到的寄存器,用戶無(wú)存和恢復(fù)它可能用到的寄存器,用戶無(wú)須保存和恢復(fù)寄存器須保存和恢復(fù)寄存器。int f(
52、int x) _asm STMFD SP,R0 ADDR0,x,#1 EOR x,R0,x LDMFD SP!,R0 return x; 對(duì)R0的恢復(fù)是不需要的對(duì)R0的保存是非法的,因?yàn)榘l(fā)生了寫之前的讀。z(4) LDM和和STM指令的寄存器列表只允指令的寄存器列表只允許物理寄存器許物理寄存器z(5) 匯編語(yǔ)言用匯編語(yǔ)言用“,”作為操作數(shù)分隔作為操作數(shù)分隔符符 z 如果有帶“,”的C語(yǔ)言表達(dá)式作為操作數(shù),必須用()將其歸為一個(gè)匯編操作數(shù)。z _asmADD x,y,(f(),z)zf(),z為一個(gè)帶有“,”的C語(yǔ)言表達(dá)式。第四節(jié)第四節(jié) C與匯編語(yǔ)言混合編程與匯編語(yǔ)言混合編程z z1. 匯編程序
53、訪問全局匯編程序訪問全局C變量變量z 匯編程序可以通過地址間接訪問在C語(yǔ)言程序中聲明的全局變量。通過使用.extern(IMPORT)關(guān)鍵詞引入全局變量,并利用LDR和STR指令根據(jù)全局變量的地址可以訪問它們。z 對(duì)于不同類型的變量,需要采用不同選項(xiàng)的LDR和STR指令,如下所示: unsigned char LDRB/STRB unsigned short LDRH/STRH unsigned int LDR/STR char LDRSB/STRSB short LDRSH/STRSH z 匯編語(yǔ)言程序讀取C語(yǔ)言程序中定義的全局變量globvar,并將其加2寫回。AREA globals,C
54、ODE,READONLYEXPORT asmsubroutine;聲明該變量可被其它文件引用IMPORT globvar ;聲明該變量是在其它文件中定義的asmsubroutineLDR R1,=globvar ;從文字池讀globvar地址送R1LDR R0,R1 ;將其值讀入到寄存器R0中ADD R0,R0,#2STR R0,R1 ;將R0值賦予變量globvarMOV PC,LRENDz2. 在在C語(yǔ)言程序中調(diào)用匯編程序語(yǔ)言程序中調(diào)用匯編程序z 匯編程序中需使用.global(EXPORT)偽操作來聲明,使得本程序可以被其它程序調(diào)用。z 在C程序調(diào)用該匯編程序之前需要在C語(yǔ)言程序中使用e
55、xtern關(guān)鍵詞來聲明該匯編程序。 C源程序源程序:# include extern void strcopy(char *d,const char *s)int main() const char *srcstr =“First stringsource”; char * dststr =“Second stringdestination”; strcopy(dststr,srcstr) return(0);用extern聲明一個(gè)外部函數(shù)調(diào)用匯編函數(shù)strcopy()匯編源程序匯編源程序:AREA SCopy,CODE,READONLYEXPORT strcopy ;用EXPORT偽操作聲明
56、該變量可以被其他文件引用Strcopy ;R0指向目標(biāo)字符串,R1指向源字符串LDRB R2,R1,#1 ;字節(jié)加載,并更新地址STRB R2,R0,#1 ;字節(jié)保存,并更新地址CMP R2,#0 ;檢測(cè)R2是否等于0BNE strcopy ;若條件不成立則繼續(xù)執(zhí)行MOV PC,LR ;從子程序返回ENDz3. 在匯編程序中調(diào)用在匯編程序中調(diào)用C語(yǔ)言程序語(yǔ)言程序z 在C程序中不需要使用任何關(guān)鍵字來聲明將被匯編語(yǔ)言調(diào)用的C程序,但是在匯編程序調(diào)用該C程序之前需要在匯編語(yǔ)言程序中使用.extern(IMPORT)偽操作來聲明該C程序。z 在匯編程序中通過BL指令來調(diào)用子程序。 C函數(shù)原型:int
57、g(int a,int b,int c,int d,int e) return a+b+c+d+e;匯編程序調(diào)用C程序g()計(jì)算5個(gè)整數(shù)i, 2*i, 3*i, 4*i, 5*i 的和。 EXPORT fAREA f,CODE,READONLYIMPORT g;聲明該變量函數(shù)g( ),i在R0中STR LR,SP,#- 4! ;預(yù)先保存LRADD R1,R0,R0;計(jì)算2 * i(第2個(gè)參數(shù))ADD R2,R1,R0;計(jì)算3*i(第3個(gè)參數(shù))ADD R3,R1,R2;計(jì)算5*i(第5個(gè)參數(shù))STR R3,SP,#- 4! ;將第5個(gè)參數(shù)壓人堆棧ADD R3,R1,R1;計(jì)算4 * i(第4個(gè)參
58、數(shù))BL g ;調(diào)用C程序g( )ADD SP,SP,#4 ;調(diào)整數(shù)據(jù)棧指針,準(zhǔn)備返回LDR PC,SP,#4 ;從子程序返回END12第四章第四章 基于基于ARM的嵌入式系統(tǒng)應(yīng)用程序設(shè)的嵌入式系統(tǒng)應(yīng)用程序設(shè)計(jì)計(jì)第五節(jié)第五節(jié) 基于基于Embest IDE for ARM環(huán)環(huán)境的軟件開發(fā)實(shí)例境的軟件開發(fā)實(shí)例z 工程編譯鏈接 z1. 開發(fā)環(huán)境的組成開發(fā)環(huán)境的組成Embest IDEARM 開發(fā)板Embest 仿真器Embest IDE開發(fā)環(huán)境z2. 開發(fā)環(huán)境的連接開發(fā)環(huán)境的連接z3. Embest IDE界面界面工程管理區(qū)代碼編輯區(qū)寄存器窗口信息提示區(qū)存儲(chǔ)器區(qū)變量窗口數(shù)據(jù)觀察區(qū)函數(shù)棧窗口Embes
59、t IDEz4. Embest IDE特征特征z(1) 支持所有ARM7,ARM9系列處理器; z(2) 支持開發(fā)語(yǔ)言:C和匯編;z(3) 支持Windows 98、XP、NT及2000等操作系統(tǒng);z(4) 源碼編輯器:支持標(biāo)準(zhǔn)的文本編輯功能,支持語(yǔ)法分色顯示。z(5) 圖形化的工程管理與設(shè)置,圖形化設(shè)置編譯連接選項(xiàng)。z(6) 調(diào)試功能:可進(jìn)行程序下載、斷點(diǎn)設(shè)置、單步執(zhí)行、異常處理等,可查看修改存儲(chǔ)區(qū)、寄存器、外圍寄存器、變量,可查看函數(shù)棧,顯示反匯編指令及源文件交叉顯示。z(7) 豐富的例程:提供Atmel、Samsung、Cirrus Logic、OKI等多家公司ARM處理器的調(diào)試程序示例
60、和使用說明。z(8) 配合Embest PowerICE仿真器,速度達(dá)120KBytes/秒。 z 在具體的編程環(huán)境下完成工程創(chuàng)建、源文件的編寫、編譯、鏈接、調(diào)試、固化等一系列工作。這就涉及到程序編譯、鏈接、調(diào)試的具體配置以及開發(fā)板上硬件的初始化、程序下載等問題。z 通過一個(gè)具體的在Embest IDE for ARM開發(fā)環(huán)境下的實(shí)際開發(fā)例程,熟悉嵌入式軟件開發(fā)的整個(gè)過程。z 例程是一個(gè)基于S3C44B0X的完整的程序,可以在RAM中進(jìn)行調(diào)試,固化在ROM中可以正常運(yùn)行。正常運(yùn)行時(shí)發(fā)光二級(jí)管LED1和LED2依次點(diǎn)亮和熄滅。z 包括:z 啟動(dòng)匯編文件44binit.sz C語(yǔ)言主源文件main
溫馨提示
- 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版體育賽事運(yùn)營(yíng)權(quán)收購(gòu)協(xié)議書范本(含贊助商權(quán)益)3篇
- 農(nóng)業(yè)科技項(xiàng)目2025年度市場(chǎng)開發(fā)與品牌建設(shè)合同3篇
- 2025版二零二五民辦學(xué)校教師職業(yè)發(fā)展規(guī)劃聘用協(xié)議4篇
- 2025年度美容美發(fā)行業(yè)技師勞動(dòng)合同續(xù)簽條件合同4篇
- 2025年度美甲店品牌形象保護(hù)與侵權(quán)糾紛處理合同4篇
- 二零二五年度車牌租賃經(jīng)營(yíng)合作協(xié)議范本3篇
- 2025年高科技研發(fā)中心投資合作框架協(xié)議3篇
- 2025年度綠化工程進(jìn)度跟蹤與管理合同4篇
- 2025年攤位電子支付系統(tǒng)合作協(xié)議3篇
- 2025年智能城市基礎(chǔ)設(shè)施建設(shè)土地買賣合同范例3篇
- 2024年住院醫(yī)師規(guī)范化培訓(xùn)師資培訓(xùn)理論考試試題
- 期末綜合測(cè)試卷(試題)-2024-2025學(xué)年五年級(jí)上冊(cè)數(shù)學(xué)人教版
- 2024年廣東省公務(wù)員錄用考試《行測(cè)》試題及答案解析
- 結(jié)構(gòu)力學(xué)本構(gòu)模型:斷裂力學(xué)模型:斷裂力學(xué)實(shí)驗(yàn)技術(shù)教程
- 黑色素的合成與美白產(chǎn)品的研究進(jìn)展
- 金蓉顆粒-臨床用藥解讀
- 法治副校長(zhǎng)專題培訓(xùn)課件
- 《幼兒園健康》課件精1
- 汽車、電動(dòng)車電池火災(zāi)應(yīng)對(duì)
- 中醫(yī)藥適宜培訓(xùn)-刮痧療法教學(xué)課件
- 免疫組化he染色fishish
評(píng)論
0/150
提交評(píng)論