最近在學(xué)習(xí)ARM公司新推出的cortex-m4系列的ARM芯片,選用的是飛思卡爾的K60系列,它采用的就是cortex-m4核心。cortex-m4比cortex-m3多了個dsp處理單元。增加了dsp單元的優(yōu)勢是顯而易見的:在涉及到大量的數(shù)學(xué)運算時可以采用dsp來處理,大大節(jié)約了運算時間和代碼量。(K60的浮點運算單元是個可選的部件,由于我拿到的K60還不支持FPU,所以下面涉及到的浮點調(diào)試只能用仿真的方式進行) 最新的KEIL MDK-ARM開發(fā)環(huán)境已經(jīng)增加了對cortex-m4的支持(我是用的是MDK-ARM Standard Version 4.20),包括仿真支持,也就是說即使你沒有拿到開發(fā)板也可以來學(xué)習(xí)cortex-m4. 在器件選擇中,這個版本已經(jīng)增加了飛思卡爾K60系列,在新建工程時可以選擇(我選擇了Freescale Semiconductor--MK60X256VMD100這個器件)。下面寫一下我自己的學(xué)習(xí)過程。
一、不使用K60的浮點運算單元。 在默認情況下,K60的浮點單元并沒有被打開,一切浮點運算還是軟件浮點。 ①打開Keil uVision4,新建工程,選擇保存路徑,選擇器件,找到Freescale Semiconductor,展開,在最下面選擇MK60X256VMD100。程序問你是否添加這個系列的啟動代碼到工程中,選擇 是(如果沒有出現(xiàn)這個選項,可以自己在Keil的安裝目錄里找,自己添加,其路徑為C:\Keil\ARM\Startup\Freescale\K60)。這時一個新的工程就建好了,默認增加了startup_MK60N512MD100.s這個啟動文件。 ②測試浮點運算。我們可以新建一個C文件,用來測試浮點運算使用的是軟浮點還是硬浮點。新建c文件里的代碼可以如下: - int main(void)
-
{
-
float a=3.14259265357,b=12.98635463738,result;
-
result=a*b*b;
-
return result;
-
-
}
-
-
extern void SystemInit(void)
-
{
-
int a=1;
-
while(a) a--;
-
}
其中void SystemInit(void)這個函數(shù)是為了滿足啟動文件startup_MK60N512MD100.s中對SystemInit的調(diào)用,本來是對器件的初始化,這里只是做測試用,沒有實際內(nèi)容。(如果要得到完整的系統(tǒng)初始化函數(shù),可以到Keil路徑C:\Keil\ARM\Startup\Freescale\K60下找到system_MK60N512MD100.c,K60的頭文件可以去Keil官方下載:http://www.keil.com/dd/chip/5359.htm)。 然后全部編譯,進入調(diào)試狀態(tài),這里默認進入的是仿真調(diào)試。 在生成的匯編代碼中我們可以看到以下內(nèi)容: 0x000002B0 E92D41F0 PUSH {r4-r8,lr} 3: float a=3.14259265357,b=12.98635463738,result; 0x000002B4 480D LDR r0,[pc,#52] ; @0x000002EC 0x000002B6 4604 MOV r4,r0 0x000002B8 480D LDR r0,[pc,#52] ; @0x000002F0 0x000002BA 4605 MOV r5,r0 4: result=a*b*b; 0x000002BC 4629 MOV r1,r5 0x000002BE 4620 MOV r0,r4 0x000002C0 F000F8A6 BL.W _fmul (0x00000410)
可以看到,生成的匯編代碼并沒有使用浮點指令(一般是以V打頭),進行乘法運算是調(diào)用在0x00000410處的_fmul函數(shù)來實現(xiàn)的,找到_fmul這個函數(shù),可以發(fā)現(xiàn)進行浮點運算是用軟件模擬的方式。
二、使用K60的浮點運算單元。 對于內(nèi)部有浮點運算單元的K60,不使用FPU就是一種資源浪費,所以要開啟它。由于默認并沒有開啟FPU運算,所以這里還有點小小的麻煩。 退出調(diào)試狀態(tài),在菜單中選擇file--Device Database...,打開器件數(shù)據(jù)庫,找到 Freescale Semiconductor--MK60X256VMD100 雙擊,在Options:中第一行后面添加空格,后面加入FPU2,這一行的最后變?yōu)?font class="Apple-style-span" color="#008080">CPUTYPE("Cortex-M4") ESEL ELITTLE FPU2,點擊Update,再點擊close關(guān)閉。 這樣這個器件就修改好了。(注:為了防止把數(shù)據(jù)庫中的器件搞亂,可以自己新建一個分類,增加一個器件,把K60這個器件的內(nèi)容統(tǒng)統(tǒng)拷進這個新建的器件里,再在這個器件里面修改其屬性) 器件修改完以后,可以再新建一個Keil工程,跟前面一樣,選擇被修改過的K60,添加啟動代碼,添加上面的main函數(shù)。這時我們可以打開工程屬性窗口,看里面的設(shè)置: Project--Options for Target 'Target1'...(或者直接按Alt+F7),在Target選項卡中,在Code Generation區(qū)域可以找到Floating Point Hardware下拉框,默認選擇了Use FPU. 工作還沒有完成,cortex-m4在默認狀態(tài)下寄存器并沒有打開浮點運算,還要修改啟動代碼。在Reset_Handler函數(shù)中,找到 LDR R0, =__main 這個代碼,在前面加入這幾行: - ; CPACR is located at address 0xE000ED88
-
LDR.W R0, =0xE000ED88
-
; Read CPACR
-
LDR R1, [R0]
-
; Set bits 20-23 to enable CP10 and CP11 coprocessors
-
ORR R1, R1, #(0xF << 20)
-
; Write back the modified value to the CPACR
-
STR R1, [R0]
上面這段代碼設(shè)定寄存器開啟了浮點運算單元,否則在執(zhí)行浮點運算代碼時會發(fā)生HardFault。 重新編譯,進入調(diào)試狀態(tài),這時可以發(fā)現(xiàn)生成的匯編代碼跟原來的不一樣了:
3: float a=3.14259265357,b=12.98635463738,result; 0x000002B0 EDDF1A0E VLDR s3,[pc,#0x38] 0x000002B4 EEF00A61 VMOV.F32 s1,s3 0x000002B8 EDDF1A0D VLDR s3,[pc,#0x34] 0x000002BC EEB00A61 VMOV.F32 s0,s3 4: result=a*b*b; 0x000002C0 EE601A80 VMUL.F32 s3,s1,s0 0x000002C4 EE611A80 VMUL.F32 s3,s3,s0 0x000002C8 EEB01A61 VMOV.F32 s2,s3
所有的浮點運算都是調(diào)用的硬件浮點運算指令,在Register觀察窗口中也多了個FPU寄存器列表。
|