《ARM原理與C程序設(shè)計》課件第五章_第1頁
《ARM原理與C程序設(shè)計》課件第五章_第2頁
《ARM原理與C程序設(shè)計》課件第五章_第3頁
《ARM原理與C程序設(shè)計》課件第五章_第4頁
《ARM原理與C程序設(shè)計》課件第五章_第5頁
已閱讀5頁,還剩204頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第五章匯編語言程序設(shè)計及

系統(tǒng)初分別化5.1ARM匯編語言程序框架5.2浮點(diǎn)數(shù)據(jù)處理5.3系統(tǒng)初始化5.4中斷服務(wù)程序本章小結(jié)5.1ARM匯編語言程序框架

在MDK環(huán)境下,新建一個工程ex5_1,拷貝工程ex4_3中的文件S3C2410A.s和initmemcon.s,然后,編寫一個新的匯編語言程序ledflash.s,其代碼如下:

1 AREALEDLIGHT,CODE,READONLY

2 EXPORT__main;LedFlash

3 EXPORT__use_two_region_memory

4GPCDAT_ADDR EQU0x56000024

5LED_ON EQU0x0000

6LED_OFF EQU0x00E0

7 ENTRY

8;LedFlash

9__main

10 LDR R0,=GPCDAT_ADDR

11 MOV R1,#LED_ON

12 STR R1,[R0] ;LEDON

13

14 BL Delay

15

16 MOV R1,#LED_OFF

17 STR R1,[R0];LEDOFF

18

19 BL Delay

20

21 B __main

22Delay

23 MOV R3,#0x0F0000

24 MOV R4,#0x0F0000

25subcycle1

26 SUB R3,R3,#1

27subcycle2

28

SUB R4,R4,#1

29 CMP R4,#0

30 BGE subcycle2

31

32 CMP R3,#0

33 BGE subcycle1

34 BX LR

35

36__use_two_region_memory;nowarning

37 END

將ledflash.s添加到工程ex5_1中,當(dāng)前工作主窗口如圖5-1所示。先不要編譯連接這個工程文件,在5.1.2小節(jié)時才能正確地編譯連接并執(zhí)行該工程。圖5-1工程ex5_1工作界面5.1.1通用輸入輸出C口配置

在圖5-1中,雙擊S3C2410A.s打開它,保持其他設(shè)置不變(相對于工程ex4_3)的情況下,對I/OConfiguration進(jìn)行配置,如圖5-2所示。

圖5-2中將PC5、PC6和PC7配置為輸出特性(Output),對應(yīng)于S3C2410A.s的第0606~0608行代碼如下:

PIOC_SETUP EQU1

PCONC_Val EQU0xAAAA56AA

PUPC_Val EQU0x00000000圖5-2通用I/O口配置

PIOC_SETUP為1表示圖5-2中的PortC被勾選;當(dāng)設(shè)置PC0~PC15如圖5-2時,端口C的控制寄存器的值為0xAAAA56AA;端口C所有上拉電阻都是使能的,端口C上拉控制寄存器的值為0x00000000。

圖5-2中的I/OConfiguration勾選,對應(yīng)于S3C2410A.s中的第0510行代碼如下:

PIO_SETUP EQU1

如圖5-2設(shè)置好之后,下面羅列出啟動代碼文件S3C2410A.s中與通用I/O口配置相關(guān)的代碼,如表5-1所示。表5-1S3C2410A.s中與I/O口配置相關(guān)的代碼序號行號注釋或語句10488;I/OPortsdefinitions20489PIO_BASEEQU0x56000000;PIOBaseAddress30490PCONA_OFSEQU0x00;PCONAOffset40491PCONB_OFSEQU0x10;PCONBOffset50492PCONC_OFSEQU0x20;PCONCOffset60493PCOND_OFSEQU0x30;PCONDOffset70494PCONE_OFSEQU0x40;PCONEOffset80495PCONF_OFSEQU0x50;PCONFOffset90496PCONG_OFSEQU0x60;PCONGOffset100497PCONH_OFSEQU0x70;PCONHOffset110498PCONJ_OFSEQU0xD0;PCONJOffset120499PUPB_OFSEQU0x18;PUPBOffset130500PUPC_OFSEQU0x28;PUPCOffset140501PUPD_OFSEQU0x38;PUPDOffset150502PUPE_OFSEQU0x48;PUPEOffset160503PUPF_OFSEQU0x58;PUPFOffset170504PUPG_OFSEQU0x68;PUPGOffset180505PUPH_OFSEQU0x78;PUPHOffset190506PUPJ_OFSEQU0xD8;PUPJOffset200509;//<e>I/OConfiguration210510PIO_SETUPEQU1220512~0536A口注釋230537PIOA_SETUPEQU0240538PCONA_ValEQU0x000003FF250540~0565B口注釋260566PIOB_SETUPEQU0270567PCONB_ValEQU0x000007FF280568PUPB_ValEQU0x00000000290570~0605C口注釋300606PIOC_SETUPEQU1310607PCONC_ValEQU0xAAAA56AA320608PUPC_ValEQU0x00000000330610~0645D口注釋340646PIOD_SETUPEQU0350647PCOND_ValEQU0x00000000360648PUPD_ValEQU0x00000000370650~0685E口注釋380686PIOE_SETUPEQU0390687PCONE_ValEQU0x00000000序號行號注釋或語句400688PUPE_ValEQU0x00000000410690~0709F口注釋420710PIOF_SETUPEQU0430711PCONF_ValEQU0x0000511A440712PUPF_ValEQU0x00000000450714~0749G口注釋460750PIOG_SETUPEQU0470751PCONG_ValEQU0x00000000480752PUPG_ValEQU0x00000000490754~0779H口注釋500780PIOH_SETUPEQU0510781PCONH_ValEQU0x000007FF520782PUPH_ValEQU0x00000000530922;I/OConfiguration540923IFPIO_SETUP<>0550924PIOA_CFG560925DCDPCONA_Val570926PIOB_CFGDCDPCONB_Val580927DCDPUPB_Val590928PIOC_CFGDCDPCONC_Val600929DCDPUPC_Val610930PIOD_CFGDCDPCOND_Val620931DCDPUPD_Val630932PIOE_CFGDCDPCONE_Val640933DCDPUPE_Val650934PIOF_CFGDCDPCONF_Val660935DCDPUPF_Val670936PIOG_CFGDCDPCONG_Val680937DCDPUPG_Val690938PIOH_CFGDCDPCONH_Val700939DCDPUPH_Val710940ENDIF720981~1038S3C2410A.s有誤,將在下面說明。

S3C2410A.s中的第0981~1038行原始代碼如下:

IF

PIO_SETUP<>0

LDRR14,=PIO_BASE

IFPIOA_SETUP<>0

ADR R0,PIOA_CFG

STR R0,[R14,#PCONA_OFS]

ENDIF

IF PIOB_SETUP<>0

ADRR0,PIOB_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONB_OFS]

STR R1,[R14,#PUPB_OFS]

ENDIF

IF PIOC_SETUP<>0

ADR R0,PIOC_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONC_OFS]

STR R1,[R14,#PUPC_OFS]

ENDIF

IF PIOD_SETUP<>0

ADR R0,PIOD_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCOND_OFS]

STR R1,[R14,#PUPD_OFS]

ENDIF

IF

PIOE_SETUP<>0

ADR R0,PIOE_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONE_OFS]

STR R1,[R14,#PUPE_OFS]

ENDIF

IF PIOF_SETUP<>0

ADR R0,PIOF_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONF_OFS]

STR R1,[R14,#PUPF_OFS]

ENDIF

IF PIOG_SETUP<>0

ADR R0,PIOG_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONG_OFS]

STR R1,[R14,#PUPG_OFS]

ENDIF

IF PIOH_SETUP<>0

ADR R0,PIOH_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONH_OFS]

STR R1,[R14,#PUPH_OFS]

ENDIF

ENDIF

修正后的代碼如下,其中,添加了注釋的為補(bǔ)充和修正的代碼行:

IF

PIO_SETUP<>0

LDRR14,=PIO_BASE

IFPIOA_SETUP<>0

ADR R0,PIOA_CFG

LDR R2,[R0];AddedbyZY

STR R2,[R14,#PCONA_OFS];ChangedbyZY

ENDIF

IFPIOB_SETUP<>0

ADR R0,PIOB_CFG

LDRR2,[R0];AddedbyZY

LDRR1,[R0,#4]

STR R2,[R14,#PCONB_OFS];ChangedbyZY

STR R1,[R14,#PUPB_OFS]

ENDIF

IFPIOC_SETUP<>0

ADR R0,PIOC_CFG

LDR R2,[R0];AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCONC_OFS]

;R0,[R14,#PCONC_OFS]ChangedbyZY

STR R1,[R14,#PUPC_OFS]

ENDIF

IFPIOD_SETUP<>0

ADR R0,PIOD_CFG

LDR R2,[R0]

;AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCOND_OFS]

;ChangedbyZY

STR R1,[R14,#PUPD_OFS]

ENDIF

IFPIOE_SETUP<>0

ADR R0,PIOE_CFG`

LDR R2,[R0];AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCONE_OFS]

;

ChangedbyZY

STR R1,[R14,#PUPE_OFS]

ENDIF

IFPIOF_SETUP<>0

ADR R0,PIOF_CFG

LDR

R2,[R0];AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCONF_OFS]

;ChangedbyZY

STR R1,[R14,#PUPF_OFS]

ENDIF

IFPIOG_SETUP<>0

ADR R0,PIOG_CFG

LDR R2,[R0];AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCONG_OFS];ChangedbyZY

STR R1,[R14,#PUPG_OFS]

ENDIF

IFPIOH_SETUP<>0

ADR R0,PIOH_CFG

LDR R2,[R0] ;AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCONH_OFS];ChangedbyZY

STR R1,[R14,#PUPH_OFS]

ENDIF

ENDIF

MDK軟件雖然是個極其優(yōu)秀的軟件包,但是,此處的錯誤是很明顯的,由于具有8個IO口,相同的錯誤連續(xù)出現(xiàn)了8次以上。例如對于C口,代碼如下:

IF PIOC_SETUP<>0

ADR R0,PIOC_CFG

LDR R1,[R0,#4]

STR R0,[R14,#PCONC_OFS]

STR R1,[R14,#PUPC_OFS]

ENDIF結(jié)合第二章,可知條件滿足,執(zhí)行完ADR指令后,R0裝入的是PIOC_CFG的標(biāo)號,即一個地址,這個地址內(nèi)的值為配置字,但是這個地址本身不能作為配置字,所以,后面的“STRR0,[R14,#PCONC_OFS]”語句就是完全錯誤的了。改正的方法很簡單,代碼如下:

IF PIOC_SETUP<>0

ADR R0,PIOC_CFG

LDR R2,[R0] ;AddedbyZY

LDR R1,[R0,#4]

STR R2,[R14,#PCONC_OFS]

;R0,[R14,#PCONC_OFS]ChangedbyZY

STR R1,[R14,#PUPC_OFS]

ENDIF像上述代碼一樣,將R0值指向的地址處的值賦給R2,然后,再使用“STRR2,[R14,#PCONC_OFS]”就可以了。對于一個商業(yè)軟件,其評估版的S3C2410芯片啟動代碼出現(xiàn)問題,一方面說明了這部分代碼沒有經(jīng)過嚴(yán)格測試,另一方面也警告我們,匯編語言編程相對于C語言來說,確有一些劣勢。

下面解釋一下表5.1和啟動代碼中關(guān)于IO口配置的方法。

序號2~19:定義了IO口存儲器映射寄存器的基地址0x56000000,然后定義了A~H口的偏移地址,這些IO口寄存器的地址可參考附表1-1。例如,C口的控制寄存器地址為0x56000020,相當(dāng)于基址0x56000000+偏移地址PCONC_OFS(0x20)。這里沒有J口,可以刪除。序號21:當(dāng)勾選了圖5-2中I/OConfiguration后,此處,PIO_SETUP為1;否則,不勾選時,PIO_SETUP為0,將不初始化IO口。

序號23~24:由于圖5-2中沒有勾選PortA,則PIOA_SETUP為0,A口只有控制寄存器,沒有上拉寄存器,這里只有PCONA_Val,當(dāng)然,這個值由于PIOA_SETUP為0而不會被用到。

序號26~28:由于圖5-2中沒有勾選PortB,則PIOB_SETUP為0;符號PCONB_Val和PUPB_Val的值表示B口的控制寄存器和上拉寄存器的配置字,這些值隨著圖形配置向?qū)Ф詣幼兓?。序?0~32:由于圖5-2中勾選了PortC,則PIOC_SETUP為1;同時,根據(jù)圖形配置向?qū)ё詣釉O(shè)置了控制寄存器和上拉寄存器的值PCONC_Val和PUPC_Val,這兩個值代表的含義請參考圖5-2和“S3C2410AUser’sManual”第九章第10頁,把GPC[7:5]設(shè)為輸出口。

序號34~52:介紹端口D~H,與上述含義相近,不再

重述。

序號54~71:如果PIO_SETUP不為0,則開辟存儲空間存放端口A~H的配置字,其中,A口只有一個配置字,B~H口均有兩個配置字。5.1.2工程ex5_1的注解及運(yùn)行情況

在前面5.1.1小節(jié)對S3C2410A.s進(jìn)行修正之后,可以編譯連接并下載這個工程了,在編譯時會報告一條警告信息,即“ex5_1.sct(8):warning:L6314W:Nosectionmatchespattern*(InRoot$$Sections)”,這里的ex5_1.sct是根據(jù)工程選項(像圖4-15那樣)的設(shè)置編譯工程時自動產(chǎn)生的存儲器配置文件,也稱Scatter文件,以?.sct結(jié)尾;“InRoot$$Section”是指為連接庫里的段分配的空間,用于C語言程序設(shè)計中。

雙擊該警告信息,則彈出ex5_1.sct文件內(nèi)容,如圖5-3所示,在“*(InRoot$$Sections)”前面加上“;”號將其注釋掉,并保存文件。圖5-3ex5_1.sct文件這時先不要編譯工程,打開工程選項,選中“Linker”頁簽,設(shè)置如圖5-4所示,即使用ScatterFile:ex5_1.sct。

說明:工程選項中的其他頁簽保持不變(相對于工程ex4_3)。

點(diǎn)擊圖5-4的“OK”按鈕后,可以重新編譯工程ex5_1,此時沒有錯誤,也沒有警告信息了,如圖5-5所示。

在圖5-5上,點(diǎn)擊“Flash|Download”菜單(或單擊工具欄上的快捷按鈕)則把ex5_1.axf下載到UP-NETARM2410實驗箱Nand型Flash上。下載完畢后,程序?qū)樱梢钥吹饺齻€LED燈在閃爍!也可以在線仿真調(diào)試(一般地,要把程序下載到Flash中后再仿真),或者把ULINK2仿真器從實驗箱上取下來,重新給實驗箱上電,則程序會從Flash中啟動執(zhí)行。圖5-4工程選項卡設(shè)置圖5-5完整的工程ex5_1本節(jié)還有兩個問題沒有解決,其一為Scatter文件如何編寫,其二為匯編語言程序ledflash.s的解釋。

筆者認(rèn)為Scatter文件的內(nèi)容及如何編寫該文件方面的知識,除了一些ARM官方的文檔之外,最好的資料是MDK軟件的幫助菜單。這個幫助菜單和它的內(nèi)容做得相當(dāng)出色!本書中,筆者幾乎無一例外地使用工程選項卡配置存儲器,因此,對Scatter文件內(nèi)容的介紹也不會很多。

現(xiàn)在,解釋一下5.1節(jié)開頭給出的程序段,即ledflash.s文件,該文件內(nèi)容如圖5-6所示,在圖5-6中給出語句的行號,下面按行號解釋。圖5-6ledflash.s文件內(nèi)容行號01:定義名為LEDLIGHT的只讀代碼段。

行號02:標(biāo)號__main在外部可見。

行號03:標(biāo)號__use_two_region_memory在外部可見。這句和行號36處沒有實際意義,僅是為了編譯時不出現(xiàn)警告或錯誤,因為在S3C2410A.s的第1095行(修正后的文件行號)有一句“IMPORT__use_two_region_memory”。

行號04:定義C口數(shù)據(jù)寄存器地址。

行號05:定義LED燈亮的常量。

行號06:定義LED燈滅的常量。行號07:ENTRY指程序入口點(diǎn),一般的匯編程序只需要有一個入口點(diǎn),而且這個入口點(diǎn)常被用作上電復(fù)位后的執(zhí)行入口點(diǎn)。需要說明的是,這里的ENTRY入口點(diǎn),并不是上電復(fù)位的執(zhí)行入口點(diǎn),在本程序中,由于RESET段是存儲在地址0x00000000處的,所以,RESET是上電復(fù)位入口點(diǎn)(RESET在S3C2410A.s文件中)。

行號09:定義標(biāo)號__main。

行號10:R0=0x56000024。

行號11:R1=0。

行號12:向地址0x56000024處賦值0,即使GPC5、GPC6和GPC7為0(低電平),由第二章圖2-26可知,將點(diǎn)亮三個LED燈。行號14:跳轉(zhuǎn)到延遲子程序,這個程序段不作介紹。

行號16:R1=0xE0。

行號17:向地址0x56000024處賦值1,即使GPC5、GPC6和GPC7為1(高電平),由第二章圖2-26可知,將熄滅三個LED燈。

行號19:跳轉(zhuǎn)到延遲子程序。

行號21:跳轉(zhuǎn)到__main,循環(huán)執(zhí)行。

程序功能:點(diǎn)亮三個LED燈后,等待約(0xF0000*0xF0000*指令周期)后,熄滅LED燈,再等待一段時間后,重新點(diǎn)亮LED燈,循環(huán)執(zhí)行,給人LED燈閃爍的感覺。5.1.3匯編語言語法

ARM匯編語言的語法內(nèi)容豐容,本書的重點(diǎn)不在于匯編語言,匯編語言主要用于初始化系統(tǒng)。因此,這里簡單地介紹一些常用的匯編語言語法。

1)?AREA

AREA已出現(xiàn)在ledflash.s中,用于定義匯編語言代碼段或數(shù)據(jù)段,例如:

AREALEDLIGHT,CODE,READONLY

AREALEDSHINE,DATA,?READWRITE上述代碼段定義一個名為LEDLIGHT的只讀代碼段和一個名為LEDSHINE的讀寫代碼段。DATA用得較少。

在S3C2410A.s中有如下語句:

AREASTACK,NOINIT,READWRITE,ALIGN=3

該語句中,NOINIT偽關(guān)鍵字表示該段代碼只分配空間,不初始化(用0填充),ALIGN=3表示按雙字對齊方式(23=8B)。

2)?SPACE

在S3C2410A.s中有如下語句:

Stack_MemSPACEStack_Size這里Stack_Mem為標(biāo)號,Stack_Size為常量,SPACE表示為Stack_Mem分配大小為Stack_Size的連續(xù)空間,單位為字節(jié)。

3)?DCD

DCD已出現(xiàn)在initmemcon.s中,表示分配字大小的連續(xù)空間,并用其他的值初始化該空間,例如:

Mem_Val_ConfDCD0x22111110,0x700

表示為標(biāo)號Mem_Val_Conf分配兩個字空間,并初始化這個字的值為0x22111110和0x700。此外,還有DCDU表示不按字對齊方式存儲,慎用??!

除了DCD之外,還有DCB、DCW、DCQ、DCFS、DCFD等,分別表示為字節(jié)、半字、雙字、單精度浮點(diǎn)數(shù)(即字)、雙精度浮點(diǎn)數(shù)(即字)分配空間,并使用指定的數(shù)據(jù)初始化。

4)?EQU

EQU是匯編語言的相等偽指令,用得較多。例如在initmemcon.s中有:

Mem_Addr_BaseEQU0x48000000

5)?PRESERVE8

PRESERVE8指定當(dāng)前文件的堆棧采用8字節(jié)對齊方式,出現(xiàn)在S3C2410A.s中第0789行,要求每個棧的長度的最低3位為0,且棧底地址的最低3位也應(yīng)為0。

6)?ARM

ARM指示符出現(xiàn)在S3C2410A.s中第0796行,指示編譯器生成32位指令的ARM代碼;而THUMB指示符表示生成16位指令的Thumb代碼。另外,THUMBX用于生成Thumb-2EE代碼。

7)?NOP

NOP即Nooperation,表示空操作。

8)?IF語句

IF語句格式為:

IF條件表達(dá)式

語句組1

ELSE

語句組2

ENDIF當(dāng)條件表達(dá)式為真時,執(zhí)行語句組1;否則,執(zhí)行語句組2。出現(xiàn)在條件表達(dá)式中的“<>”(例如S3C2410A.s中的第0923行)表示不等于。表示等于、大于、小于、大于等于、小于等于的關(guān)系操作符為=、>、<、>=、<=。

9)?IMPORT

IMPORT后面跟標(biāo)識符,表明該標(biāo)識符是在該文件外部定義的,標(biāo)識符后可以加可選項[WEEK],則引用的標(biāo)識符沒有定義時,編譯時也不會出錯。而該文件中定義的標(biāo)識符需要被工程中的其他文件引用時,使用EXPORT關(guān)鍵字。同時,GLOBAL可以聲明一個全局標(biāo)識符。此外,EXTERN的功能與IMPORT相似,當(dāng)該文件中沒有實際引用這個標(biāo)識符時,EXTERN下編譯器不會添加該標(biāo)識符到符號表中。

10)邏輯操作

S3C2410A.s的第1054行出現(xiàn)了“:OR:”,表示按位取或,還有以下偽操作符:

:AND:表示按位取與;:EOR:表示按位取異或;:NOT:表示取反。

同時,還有:MOD:?表示取模,:SHL:、:SHR:、:ROL:?和:?ROR:?分別表示左移、右移、循環(huán)左移、循環(huán)右移,還可以使用+、-、*、/算符,其中“+”出現(xiàn)在S3C2410A.s的第

1100行。

表示邏輯操作的有:LNOT:、:LAND:、:LOR:和:LEOR:,依次為邏輯取反、邏輯與、邏輯或、邏輯異或。

11)?END

匯編語言每個程序段均以END結(jié)尾。

匯編語言程序是由AREA定義的一個個代碼段組成的,每個代碼段由匯編指令語句組成,完成某項特定的功能,最后以END結(jié)尾。不同的代碼段之間可以通過引用標(biāo)號的方式相互調(diào)用。工程ex5_1包含了匯編語言程序的基本特征,可以視為匯編語言程序的學(xué)習(xí)框架程序。在5.4節(jié)中還將添加中斷處理進(jìn)一步完善該程序。

5.2浮點(diǎn)數(shù)據(jù)處理

浮點(diǎn)數(shù)即小數(shù),使用ARM匯編語言表示和處理小數(shù),需要借助于IEEE-754標(biāo)準(zhǔn)或者DSP定標(biāo)的方法。DSP定標(biāo)方法在定點(diǎn)DSP芯片進(jìn)行浮點(diǎn)數(shù)據(jù)處理時經(jīng)常使用,相關(guān)內(nèi)容可參考《TMS320C5000系列DSP匯編語言程序設(shè)計》第六章,在這一章中,作者指出,“匯編語言是公認(rèn)的硬件操作最好的語言,并且用它來編寫算法對編程者的思維也是一個很好的啟迪過程?!笔聦嵣?,由于匯編語言語法簡單明了,用來實現(xiàn)算法時,沒有現(xiàn)成的算法庫來調(diào)用,因此,編程者必須親自編寫算法的每個函數(shù)和每個細(xì)節(jié),從而要求編程者對算法非常熟悉才行。本節(jié)內(nèi)容將介紹ARM920T下的數(shù)值定標(biāo)和正余弦函數(shù)的計算。5.2.1計算基礎(chǔ)

計算正弦和余弦函數(shù)的值,需要借助于泰勒級數(shù)展開式,如下:例如,取x=0.45,則(1)(2)上兩式為本節(jié)程序采用的算法。5.2.2數(shù)值定標(biāo)

匯編語言中的32位操作數(shù)只能為0或1組成的碼字。所謂“碼字”,是指CPU只能把存儲器的內(nèi)容視為二進(jìn)制數(shù)碼符號(實際上是電平信號),而不是數(shù)字。人們習(xí)慣把二進(jìn)制碼字之間的運(yùn)算關(guān)系稱為二進(jìn)制數(shù)(二進(jìn)制補(bǔ)碼)之間的運(yùn)算,所以常常給人一種存儲器存儲的是數(shù)的假象。但是,在碼和數(shù)之間的確有一種一一映射的關(guān)系,并且,在這個映射關(guān)系上可以將數(shù)的運(yùn)算映射為碼間的運(yùn)算。同時,由于十六進(jìn)制表示的整數(shù)和碼字之間這種映射關(guān)系非常直觀,以至于人們會忽略這種映射的存在。例如,給定一個十六進(jìn)制碼字0x00000055,人們會不加思考地認(rèn)為它等于十進(jìn)制數(shù)85。這種相等是有條件的,即0x00000055碼字的小數(shù)定標(biāo)點(diǎn)位于第0位以后(或認(rèn)為沒有小數(shù)定標(biāo)點(diǎn)),這個定標(biāo)點(diǎn)是思想中添加的、用于碼和數(shù)之間映射的一種關(guān)系。對于整數(shù)的處理,人們可以很直觀地認(rèn)為這個定標(biāo)點(diǎn)不存在。對于小數(shù)處理,就不能忽視這個定標(biāo)點(diǎn)了。定標(biāo)的方法就是通過加定標(biāo)的方法將小數(shù)轉(zhuǎn)化為十六進(jìn)制數(shù)(碼)的方法,ARM是32位定點(diǎn)處理器,定標(biāo)點(diǎn)可設(shè)為0~32。定標(biāo)點(diǎn)確定后,32位的存儲字存儲的數(shù)據(jù)大小也就確定了。一個小數(shù)a的n定標(biāo)值為取整(a×2n),0≤n≤32。根據(jù)這種方法,小數(shù)0.45的31定標(biāo)值為0.45×231=966367641.6d≈966367641d=

0x39999999,即設(shè)置定標(biāo)點(diǎn)為31后,十六進(jìn)制值0x39999999不再是整數(shù)966367641,而是小數(shù)0.45。定標(biāo)有一種記號法,即Q(32-n).n,定標(biāo)點(diǎn)為31時,記作Q1.31,有時簡記為Q31,是最常用的一種定標(biāo)方法。但是,Q31定標(biāo)只能表示[-1,1)區(qū)間的小數(shù),如果表示更大范圍內(nèi)的小數(shù),例如區(qū)間[-2,2),則需要采用定標(biāo)Q2.30。小數(shù)定標(biāo)后的值往往是小數(shù)的近似值,這說明計算機(jī)采用定標(biāo)方法只能不精確地表示小數(shù),例如,小數(shù)0.1就不能精確定標(biāo)。小數(shù)的定標(biāo)值可參與加、減和乘等運(yùn)算,由于定標(biāo)值表示的數(shù)據(jù)范圍有限,所以定標(biāo)值間的運(yùn)算不能有溢出,否則計算結(jié)果錯誤。特別是乘法運(yùn)算,乘法結(jié)果為64位,定標(biāo)點(diǎn)位置移動到62位,必須取高32位(同時向左移一位)進(jìn)行定標(biāo)點(diǎn)的還原(為31位);加法和減法運(yùn)算不改變定標(biāo)點(diǎn)。常用的做法為:在十進(jìn)制數(shù)條件下進(jìn)行小數(shù)的算法處理,找到所有參與運(yùn)算的小數(shù)、中間結(jié)果和最終結(jié)果的絕對值最大值,按照這個最大值確定定標(biāo)點(diǎn)位置。然后,將小數(shù)轉(zhuǎn)換為定標(biāo)值,編寫匯編語言程序?qū)Χ?biāo)值進(jìn)行處理,得到定標(biāo)值表示的最終結(jié)果。最后,用去定標(biāo)的方法,即最終結(jié)果除去2n后得到真實的小數(shù)形式結(jié)果。在這個過程中,只有上一行的陰影部分是ARM匯編語言程序完成的。計算0.45的正弦和余弦值匯編語言程序,由于輸入數(shù)據(jù)、中間結(jié)果和最終結(jié)果都不可能超過1,可以采用Q31定標(biāo)方法。

需要指出的是,上述介紹的是有符號的定標(biāo),即定標(biāo)值的最高位31位為符號位,這種定標(biāo)方法用得較多。關(guān)于無符號定標(biāo)方法,由于與有符號定標(biāo)方法相似,故本書不作介紹。

下面把公式(1)和(2)中出現(xiàn)的常數(shù)按Q31定標(biāo)方法計算的定標(biāo)值列于表5-2中。表5-2公式(1)和(2)中常數(shù)的Q31定標(biāo)值小數(shù)0.451/3!1/5!1/7!定標(biāo)值0x399999990x155555550x11111110x68068小數(shù)11/2!1/4!1/6!定標(biāo)值0x7FFFFFFF0x400000000x55555550x2D82D8這里的定標(biāo)點(diǎn)和小數(shù)點(diǎn)是完全不同的概念,請注意區(qū)分。5.2.3程序代碼及結(jié)果分析

本小節(jié)的內(nèi)容不是本書的重點(diǎn),因此對本小節(jié)中的匯編程序不作深入分析,但是我們還是給出了完整的程序示例和源代碼(注釋清晰),供感興趣的讀者參考。

在工程ex5_1的基礎(chǔ)上,新建工程ex5_2,修改ledflash.s文件,其代碼如下所示:

1 AREALEDLIGHT,CODE,READONLY

2 EXPORT__main;LedFlash

3 EXPORT__use_two_region_memory

4

5 IMPORTSin0p45;forSincos0.45

6GPCDAT_ADDR EQU0x56000024

7LED_ON EQU0x0000

8LED_OFF EQU0x00E0

9 ENTRY

10;LedFlash

11__main

12 BL Sin0p45;forSincos0.45

13ledflash

14 LDR R0,=GPCDAT_ADDR

15 MOV R1,#LED_ON16 STR R1,[R0] ;LEDON

17

18 BL Delay

19

20 MOV R1,#LED_OFF

21 STR R1,[R0]

;LEDOFF

22

23 BL Delay

24

25 B ledflash

26Delay

27 MOV R3,#0x0F0000

28 MOV R4,#0x0F0000

29subcycle1

30 SUB

R3,R3,#1

31subcycle2

32

SUB

R4,R4,#1

33 CMP R4,#0

34 BGE subcycle2

35

36 CMP R3,#0

37 BGE subcycle1

38 BX LR

39

40__use_two_region_memory;nowarning

41 END

上述代碼中后跟注釋“;forSincos0.45”的語句為新添加的語句,即先進(jìn)行求正余弦值的運(yùn)算,然后再作使LED燈閃爍的處理。

新建匯編語言文件sincos0p45.s,并添加到工程ex5_2中,工程ex5_2的主界面如圖5-7所示。圖5-7工程ex5_2的工作界面文件sincos0p45.s的完整代碼如下:

1AREASINCOS,CODE,READONLY

2 ?EXPORTSin0p45

3Sin0p45

4 STMFDSP!,{R0-R9,R14}

5

6 ;calculatesin0.45

7 ;R0-R1loadaddress

8 ;R3-R8loadvalue

9 ADRR0,x_q ;R0isaddrofx

10 LDRR4,[R0] ;R4=x

11

12 SMULL R5,R6,R4,R4

13 MOV R7,R6,LSL#1

14 ADD R7,R7,R5,LSR#31;R7=x*x

15

16

SMULL R5,R6,R4,R7

17 MOV R8,R6,LSL#1

18 ADD R8,R8,R5,LSR#31;R8=x*x*x

19

20 ADR R1,cof_3

21 LDR

R3,[R1]

;R3=cof3

22

23 SMULL

R5,R6,R3,R8

24 MOV

R2,R6,LSL#1

25 ADD

R2,R2,R5,LSR#31

;R2=x^3/3!

26

27 MOV

R9,R4

28 SUB

R9,R9,R2

;R9=x-x^3/3!

29

30 SMULL R5,R6,R7,R8

31 MOV R8,R6,LSL#1

32 ADD R8,R8,R5,LSR#31

;R8=x^5

33

34 ADR R1,cof_5

35 LDR R3,[R1];R3=cof5

36

37 SMULL R5,R6,R3,R8

38 MOV R2,R6,LSL#1

39 ADD R2,R2,R5,LSR#31

;R2=x^5/5!

40

41 ADD R9,R9,R2;R9=x-x^3/3!+x^5/5!

42

43 SMULL R5,R6,R7,R8

44 MOV R2,R6,LSL#1

45 ADD R2,R2,R5,LSR#31 ;R2=x^7

46

47 ADR R1,cof_7

48 LDR R3,[R1] ;R3=cof7

49

50SMULL R5,R6,R3,R2

51 MOV R2,R6,LSL#1

52

ADDR2,R2,R5,LSR#31;R2=x^7/7!

53

54

SUBR9,R9,R2;R9=x-x^3/3!+x^5/5!-x^7/7!

55

56LDRR1,=sin_x

57STRR9,[R1]

58

59;calculatecos0.45

60ADR R0,x_q ;R0isaddrofx

61LDR R4,[R0] ;R4=x

62

63 SMULL R5,R6,R4,R4

64 MOV R7,R6,LSL#1

65 ADD R7,R7,R5,LSR#31;R7=x*x

66

67

SMULL R5,R6,R7,R7

68 MOV R8,R6,LSL#1

69 ADD R8,R8,R5,LSR#31;R8=x^4

70

71 ADR R1,cof_2

72 LDR R3,[R1];R3=cof2

73

74 SMULL R5,R6,R3,R7

75 MOV R2,R6,LSL#1

76 ADD R2,R2,R5,LSR#31 ;R2=x^2/2!

77

78 ADR R0,cof_1

79 LDR R9,[R0]

80 SUB

R9,R9,R2;R9=1-x^2/2!

81

82 ADR

R1,cof_4

83 LDR

R3,[R1];R3=cof4

84

85 SMULL R5,R6,R3,R8

86 MOV R2,R6,LSL#1

87 ADD R2,R2,R5,LSR#31 ;R2=x^4/4!

88

89 ADD R9,R9,R2;R9=1-x^2/2!+x^4/4!

90

91 SMULL

R5,R6,R7,R8

92 MOV R2,R6,LSL#1

93 ADD R2,R2,R5,LSR#31;R2=x^6

94

95 ADRR1,cof_6

96 LDRR3,[R1];R3=cof6

97

98 SMULLR5,R6,R3,R2

99 MOVR2,R6,LSL#1

100 ADDR2,R2,R5,LSR#31;

R2=x^6/6!

101

102 SUB R9,R9,R2;R9=1-x^2/2!+x^4/4!-x^6/6!

103

104 LDRR1,=cos_x

105 STR R9,[R1]

106

107 ;BX LR

;return

108 LDMFD SP!,{R0-R9,PC};return

109

110x_q DCD0x39999999;0.45

111cof_1 DCD0x7FFFFFFF ;1

112cof_2 DCD0x40000000 ;1/2!

113cof_3 DCD0x15555555 ;1/3!

114cof_4 DCD0x05555555 ;1/4!

115cof_5 DCD0x01111111 ;1/5!

116cof_6 DCD0x002D82D8 ;1/6!

117cof_7 DCD0x00068068;1/7!

118

119 AREASINCOSRES,DATA,READWRITE

120sin_x DCD0 ;sin0.45

121cos_x DCD0 ;cos0.45

122 END

編譯連接下載工程ex5_2,然后調(diào)試工程,如圖5-8所示。圖5-8工程ex5_2的調(diào)試窗口工程ex5_2的計算結(jié)果sin0.45和cos0.45保存在標(biāo)號sin_x和cos_x處,即圖5-8右側(cè)Memory的0x30000000和0x30000004處,計算結(jié)果數(shù)值為0x37ACF357和0x7341D96B,去定標(biāo)后的值(即轉(zhuǎn)化為十進(jìn)制數(shù),再除以231后的值)為:

計算值sin0.45=0.4349655318073928356170654296875

計算值cos0.45=0.9004470608197152614593505859375而真實值為:

真實值sin0.45=0.4349655341112302104208442462319

真實值cos0.45=0.90044710235267692166884061148645

計算值和真實值的誤差在10-7數(shù)量級上,可見,計算結(jié)果是正確的。(數(shù)學(xué)角度上,還要考慮級數(shù)的截斷誤差!)

5.3系統(tǒng)初始化

系統(tǒng)初始化是指上電復(fù)位后ARM芯片級程序首先要進(jìn)行的處理,即配置工作時鐘、看門狗電路、存儲器空間、通用IO口、中斷向量表及堆棧等,這些工作都可以借助MDK軟件的啟動代碼可視化配置向?qū)瓿?,生成相關(guān)的啟動代碼文件。這里選用了S3C2410芯片,所以啟動代碼文件為S3C2410A.s。下面將介紹這個啟動代碼文件中還沒有講述的部分,并編制一個替換掉該啟動代碼文件的初始化代碼文件。5.3.1啟動代碼S3C2410A.s

啟動代碼文件S3C2410A.s中已經(jīng)講述的部分為存儲器控制器、通用IO口配置以及堆和棧等四部分,本小節(jié)中介紹的內(nèi)容為看門狗定時器(WatchdogTimer)、時鐘管理器(ClockManagement)和中斷向量表(InterruptVectorTable)三部分,其中,中斷向量表在5.4節(jié)還要深入講述。

1.時鐘管理器

初始化時鐘管理器往往是初始化工作的第一步(例如DSP中),而在啟動文件S3C2410A.s中,第一步是初始化看門狗定時器,第二步是初始化時鐘管理器。結(jié)合“S3C2410AUser’sManual”第七章“Clock&PowerManagement”,可知時鐘管理器如圖5-9所示。

S3C2410A有四種工作模式,即正常模式、慢速模式、空閑模式和掉電模式,正常模式下由圖5-9所示模塊向CPU和所有外設(shè)提供時鐘源,外設(shè)時鐘源可以通過軟件打開或關(guān)閉,當(dāng)所有外設(shè)時鐘都工作時,芯片功耗達(dá)到最大。這里僅討論正常模式下的時鐘管理器配置。

從UP-NETARM2410實驗箱原理圖上可以查到,S3C2410A的OM3和OM2腳均接地,即OM[3:2]=0b00,則由S3C2410A芯片資料手冊可以查到,此時上電復(fù)位后時鐘配置為MPLL有效、UPLL有效、主時鐘源和USB時鐘源均來自外部的晶體。再查UP-NETARM2410實驗箱原理圖,可以查到PLL時鐘源頻率為12?MHz,RTC時鐘源為32.768?kHz。圖5-9S3C2410A時鐘管理器從附錄一的附表1-1可以查到與時鐘管理器相關(guān)的映射寄存器共有6個,即LOCKTIME、MPLLCON(必須初始化)、UPLLCON、CLKCON、CLKSLOW和CLKDIVN,基地址為0x4C000000,偏移量依次為0、0x4、0x8、0xC、0x10和0x14。這些寄存器的含義請參考S3C2410A芯片資料手冊第七章。這些寄存器統(tǒng)稱為時鐘控制寄存器,配置好這些寄存器后,輸入到芯片的時鐘將按圖5-10進(jìn)行分配,其中,F(xiàn)CLK給CPU,HCLK給AHB總線外設(shè)(例如ARM920T、存儲控制器、中斷控制器、LCD控制器、DMA和USB主機(jī)等),PCLK給APB總線外設(shè)(例如WDT、IIS、IIC、PWM定時器、MMC接口、ADC、UART、GPIO、RTC和SPI等),UCLK為USB服務(wù)。圖5-10S3C2410A時鐘分配方案現(xiàn)在看一下啟動代碼S3C2410A.s中與配置6個時鐘控制寄存器相關(guān)的語句,如表5-3所示,其中,行號以工程ex5_1中的S3C2410A.s為準(zhǔn)。表5-3S3C2410A.s中與時鐘控制器相關(guān)的代碼序號行號注釋或語句10068~0076;ClockManagementdefinitionsCLK_BASE EQU 0x4C000000 ;ClockBaseAddressLOCKTIME_OFS EQU 0x00 ;LOCKTIMEOffsetMPLLCON_OFS EQU 0x04 ;MPLLCONOffsetUPLLCON_OFS EQU 0X08 ;UPLLCONOffsetCLKCON_OFS EQU 0x0C ;CLKCONOffsetCLKSLOW_OFS EQU 0x10 ;CLKSLOWOffsetCLKDIVN_OFS EQU 0X14 ;CLDKIVNOffsetCAMDIVN_OFS EQU 0X18 ;CAMDIVNOffset20080~0140;時鐘控制器寄存器注釋30141~0147CLK_SETUP EQU 1MPLLCON_Val EQU 0x0005C080UPLLCON_Val EQU 0x00028080CLKCON_Val EQU 0x0007FFF0CLKSLOW_Val EQU 0x00000004LOCKTIME_Val EQU 0x00FFFFFFCLKDIVN_Val EQU 0X00000000序號行號注釋或語句40909~0918;ClockManagementConfigurationIFCLK_SETUP<>0CLK_CFGDCD LOCKTIME_ValDCD CLKDIVN_ValDCD MPLLCON_ValDCD UPLLCON_ValDCD CLKSLOW_ValDCD CLKCON_ValENDIF50958~0968IFCLK_SETUP<>0LDR R0,=CLK_BASEADR R8,CLK_CFGLDMIA? R8,{R1-R6}STR? R1,[R0,#LOCKTIME_OFS]STR? R2,[R0,#CLKDIVN_OFS]STR? R3,[R0,#MPLLCON_OFS]STR? R4,[R0,#UPLLCON_OFS]STR? R5,[R0,#CLKSLOW_OFS]STR? R6,[R0,#CLKCON_OFS]ENDIF表5-3中序號1一行表示定義時鐘控制寄存器的基地址和偏移量;序號3一行中,CLK_SETUP為1表示在配置向?qū)е小癈lockManagement”勾選,即使用S3C2410A.s初始化時鐘寄存器,其他的為6個寄存器的配置值;序號4中為時鐘控制寄存器配置字分配空間;序號5一行為初始化時鐘控制寄存器。(這段代碼寫得不錯!)下面理解一下表5-3中序號3一行中各配置字的含義,如表5-4所示,表5-4中也列出筆者擬配置的值,其中,“MDK值”表示MDK軟件啟動代碼中配置的值,“筆者值”為筆者擬定的值。表5-4時鐘控制寄存器配置值及含義寄存器名MDK值筆者值含義LOCKTIME0x00FFFFFF0x00FFFFFF

LOCKTIME的位[23:12]為UPLL的鎖定時間,位[11:0]為MPLL的鎖定時間,位[31:24]保留。這里采用復(fù)位值,也是最大值,MPLL和UPLL穩(wěn)定(鎖住)前的計數(shù)值均為0xFFFMPLLCON0x0005C0800x00058011

MPLLCON和UPLLCON結(jié)構(gòu)相同,第[19:12]位為MDIV,第[9:4]位為PDIV,第[1:0]位為SDIV,其他位保留。Mpll時鐘值=[輸入時鐘*(MDIV+8)]/[(PDIV+2*2SDIV],MDK的設(shè)置值為默認(rèn)值,表示Mpll為120?MHz,筆者的設(shè)置值為192?MHz。注意:雖然這款S3C2410A芯片最大工作頻率為200?MHz,但是配置PLL值應(yīng)使用推薦的配置,不要任意設(shè)置UPLLCON0x000280800x00078023

MDK的配置值為57.6?MHz,筆者的設(shè)定值為48?MHz寄存器名MDK值作者值含義CLKCON0x0007FFF00x0007FFF0

CLKCON寄存器從第18位至第4位依次管理SPI、IIS、IIC、ADC(含觸摸屏)、TRC、GPIO、UART2、UART1、UART0、SDI、PWMTIMER、USB設(shè)備、USB主機(jī)、LCDC、NandFlash的時鐘源。當(dāng)各位取1時有效;取0時無效。第3位至第0位依次為POWER_OFF模式、空閑模式、保留、SM_BIT(推薦為0)的設(shè)置位,均需取0。采用的是缺省設(shè)置CLKSLOW0x000000040x00000004

CLKSLOW寄存器第7位為1表示UCLK開,為0表示UCLK關(guān)(UPLL終始有效)。第5位為1表示PLL開,為0表示PLL關(guān)。第4位為0表示FCLK=Mpll,為1表示SLOW模式(此時時鐘大小計算請參考S3C2410A手冊)。第[2:0]位為慢時鐘分頻值,缺省為0x4。這里采用缺省值即可CLKDIVN0x000000000x00000003

CLKDIVN寄存器第1位為0,則HCLK時鐘為FCLK;第1位為1,則HCLK時鐘為FCLK/2。第0位為0,表示PCLK時鐘為HCLK;第0位為1,表示PCLK時鐘為HCLK/2。第2位為0,保留;如果第2位設(shè)為1,表示HCLK和PCLK均為FCLK./4,此時位[1:0]無效,且必須設(shè)為0b00結(jié)合圖5-9和圖5-10,配置時鐘寄存器后,Mpll時鐘穩(wěn)定前,CPU直接使用外部時鐘;當(dāng)PLL穩(wěn)定后,CPU時鐘FCLK將使用Mpll時鐘,即工作在192MHz下。

在工程ex5_1的基礎(chǔ)上新建工程ex5_3(此時,與工程ex5_1完全相同),然后,按表5-4中的“作者值”設(shè)置S3C2410A.s,如圖5-11所示。圖5-11

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論