你好!
按规格书上说,现在的M4内带有DSP。
我在程序的初始化的时候,利用ROM_FPULazyStackingEnable();使能了浮点运算,那么如果我在做些浮点或是整形的运算,或是一些算法的时候,M4 自己会用DSP做运算,还是需要人为干预?还是有库可用?
谢谢。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
你好!
按规格书上说,现在的M4内带有DSP。
我在程序的初始化的时候,利用ROM_FPULazyStackingEnable();使能了浮点运算,那么如果我在做些浮点或是整形的运算,或是一些算法的时候,M4 自己会用DSP做运算,还是需要人为干预?还是有库可用?
谢谢。
你的问题其实是两个问题:
1. cortex-M4的内核带有一个FPU的运算单元,当你开启了该运算单元后,编译器会把你需要做浮点运算的自动用浮点汇编指令来编译,你可以用汇编的窗口来观察,如果启动了FPU单元,你的运算会被编译成用V开头的汇编指令,这就是FPU单元的汇编指令。不需要你做其他工作。
2. 至于DSP功能,其实是厂家开发的DSP算法库,你可以在工程中添加IQmath的lib文件,在代码中调用DSP的算法函数。具体的用法你需要看相关的用户手册。
补充一点,如果要用FPU单元,不光要在代码中使能FPU,而且还要在编译器的选项开启FPU单元功能,这样编译出来的汇编代码才会有带V开头的FPU单元汇编代码.
你好!
为了验证CORTEX-M4的FPU运算单元,我做了以下测试,建立了一个函数:
static float data_test[512]; // data_test[512]在main里面已经初始化了
float test_fpu(void)
{
float return_data;
short int i;
for (i = 0; i<510;i++)
{
return_data += data_test[i]*data_test[i+1]*data_test[i+2];
return_data = return_data/0.000569;
}
void main(void)
{
把某一管脚置高;
test_fpu();
把某一管脚置低;
}
我发现如下情况:
1. 系统在初始化的时候,如果调用
MAP_FPUEnable();
MAP_FPULazyStackingEnable();
那么,这个函数执行时间是10.4ms
2. 初始化的时候,不调用上面两个函数,那么时间是8.4ms。
3. 你说的编译器使能FPU,是不是在"build --> ARM Compiler --> processor options ---> "Specify floating point support 这里选FPv4SPD16",我这个地方选了,但是发现没有什么作用。(还是说我设错了,应该设定其它地方)。
在上面的三个实验里,都没有看到带V的汇编指令。
您好,我做了FPU的实验,但是还是没有看到有带V开头的FPU单元汇编代码。
下面是CCS编译楼主提供的程序, test_fpu函数,得到的结果,使用浮点的代码我标记出来了。
除了使用带V的指令以外,使用Sx寄存器也是使用浮点单元的特征。
;*****************************************************************************
;* FUNCTION NAME: test_fpu *
;* *
;* Regs Modified : A1,A2,A3,A4,V1,V9,SP,LR,SR,D0,D0_hi,D1,FPEXC,FPSCR *
;* Regs Used : A1,A2,A3,A4,V1,V9,SP,LR,SR,D0,D0_hi,D1,FPEXC,FPSCR *
;* Local Frame Size : 0 Args + 8 Auto + 8 Save = 16 byte *
;*****************************************************************************
test_fpu:
;* --------------------------------------------------------------------------*
.dwcfi cfa_offset, 0
PUSH {A3, A4, V1, LR} ; [DPU_3_PIPE]
.dwcfi cfa_offset, 4
.dwcfi save_reg_to_mem, 14, -4
.dwcfi cfa_offset, 8
.dwcfi save_reg_to_mem, 4, -8
.dwcfi cfa_offset, 12
.dwcfi save_reg_to_mem, 3, -12
.dwcfi cfa_offset, 16
.dwcfi save_reg_to_mem, 2, -16
.dwcfi cfa_offset, 16
$C$DW$3 .dwtag DW_TAG_variable, DW_AT_name("return_data")
.dwattr $C$DW$3, DW_AT_TI_symbol_name("return_data")
.dwattr $C$DW$3, DW_AT_type(*$C$DW$T$16)
.dwattr $C$DW$3, DW_AT_location[DW_OP_breg13 0]
$C$DW$4 .dwtag DW_TAG_variable, DW_AT_name("i")
.dwattr $C$DW$4, DW_AT_TI_symbol_name("i")
.dwattr $C$DW$4, DW_AT_type(*$C$DW$T$8)
.dwattr $C$DW$4, DW_AT_location[DW_OP_breg13 4]
.dwpsn file "../main.c",line 7,column 7,is_stmt,isa 1
MOVS A1, #0 ; [DPU_3_PIPE] |7|
STRH A1, [SP, #4] ; [DPU_3_PIPE] |7|
.dwpsn file "../main.c",line 7,column 14,is_stmt,isa 1
LDRSH A1, [SP, #4] ; [DPU_3_PIPE] |7|
CMP A1, #510 ; [DPU_3_PIPE] |7|
BGE ||$C$L2|| ; [DPU_3_PIPE] |7|
; BRANCHCC OCCURS {||$C$L2||} ; [] |7|
;* --------------------------------------------------------------------------*
;* BEGIN LOOP ||$C$L1||
;*
;* Loop source line : 7
;* Loop closing brace source line : 11
;* Known Minimum Trip Count : 1
;* Known Maximum Trip Count : 4294967295
;* Known Max Trip Count Factor : 1
;* --------------------------------------------------------------------------*
||$C$L1||:
$C$DW$L$test_fpu$2$B:
.dwpsn file "../main.c",line 9,column 3,is_stmt,isa 1
LDRSH A2, [SP, #4] ; [DPU_3_PIPE] |9|
LDR A1, $C$CON1 ; [DPU_3_PIPE] |9|
ADD A1, A1, A2, LSL #2 ; [DPU_3_PIPE] |9|
LDRSH A2, [SP, #4] ; [DPU_3_PIPE] |9|
VLDR.32 S0, [A1, #0] ; [DPU_LIN_PIPE] |9|
MOVS A1, #4 ; [DPU_3_PIPE] |9|
ADD A1, A1, A2, LSL #2 ; [DPU_3_PIPE] |9|
LDR A2, $C$CON1 ; [DPU_3_PIPE] |9|
ADDS A2, A2, A1 ; [DPU_3_PIPE] |9|
VLDR.32 S1, [A2, #0] ; [DPU_LIN_PIPE] |9|
MOVS A1, #8 ; [DPU_3_PIPE] |9|
LDRSH A2, [SP, #4] ; [DPU_3_PIPE] |9|
VMUL.F32 S0, S1, S0 ; [DPU_LIN_PIPE] |9|
ADD A1, A1, A2, LSL #2 ; [DPU_3_PIPE] |9|
LDR A2, $C$CON1 ; [DPU_3_PIPE] |9|
VLDR.32 S1, [SP, #0] ; [DPU_LIN_PIPE] |9|
ADDS A2, A2, A1 ; [DPU_3_PIPE] |9|
VLDR.32 S2, [A2, #0] ; [DPU_LIN_PIPE] |9|
VMLA.F32 S1, S2, S0 ; [DPU_LIN_PIPE] |9|
VSTR.32 S1, [SP, #0] ; [DPU_LIN_PIPE] |9|
.dwpsn file "../main.c",line 10,column 3,is_stmt,isa 1
LDR A1, [SP, #0] ; [DPU_3_PIPE] |10|
$C$DW$5 .dwtag DW_TAG_TI_branch
.dwattr $C$DW$5, DW_AT_low_pc(0x00)
.dwattr $C$DW$5, DW_AT_name("__aeabi_f2d")
.dwattr $C$DW$5, DW_AT_TI_call
BL __aeabi_f2d ; [DPU_3_PIPE] |10|
; CALL OCCURS {__aeabi_f2d } ; [] |10|
ADR V1, $C$FL1 ; [DPU_3_PIPE] |10|
LDMIA V1, {A3,A4} ; [DPU_3_PIPE] |10|
$C$DW$6 .dwtag DW_TAG_TI_branch
.dwattr $C$DW$6, DW_AT_low_pc(0x00)
.dwattr $C$DW$6, DW_AT_name("__aeabi_ddiv")
.dwattr $C$DW$6, DW_AT_TI_call
BL __aeabi_ddiv ; [DPU_3_PIPE] |10|
; CALL OCCURS {__aeabi_ddiv } ; [] |10|
$C$DW$7 .dwtag DW_TAG_TI_branch
.dwattr $C$DW$7, DW_AT_low_pc(0x00)
.dwattr $C$DW$7, DW_AT_name("__aeabi_d2f")
.dwattr $C$DW$7, DW_AT_TI_call
BL __aeabi_d2f ; [DPU_3_PIPE] |10|
; CALL OCCURS {__aeabi_d2f } ; [] |10|
VMOV S0, A1 ; [DPU_LIN_PIPE] |10|
VSTR.32 S0, [SP, #0] ; [DPU_LIN_PIPE] |10|
.dwpsn file "../main.c",line 7,column 20,is_stmt,isa 1
LDRSH A1, [SP, #4] ; [DPU_3_PIPE] |7|
ADDS A1, A1, #1 ; [DPU_3_PIPE] |7|
STRH A1, [SP, #4] ; [DPU_3_PIPE] |7|
.dwpsn file "../main.c",line 7,column 14,is_stmt,isa 1
LDRSH A1, [SP, #4] ; [DPU_3_PIPE] |7|
CMP A1, #510 ; [DPU_3_PIPE] |7|
BLT ||$C$L1|| ; [DPU_3_PIPE] |7|
; BRANCHCC OCCURS {||$C$L1||} ; [] |7|
$C$DW$L$test_fpu$2$E:
;* --------------------------------------------------------------------------*
.dwpsn file "../main.c",line 12,column 1,is_stmt,isa 1
;* --------------------------------------------------------------------------*
||$C$L2||:
.dwcfi cfa_offset, 16
$C$DW$8 .dwtag DW_TAG_TI_branch
.dwattr $C$DW$8, DW_AT_low_pc(0x00)
.dwattr $C$DW$8, DW_AT_TI_return
POP {A3, A4, V1, PC} ; [DPU_3_PIPE]
; BRANCH OCCURS ; []