SAM4E单片机之旅——24、使用DSP库求向量数量积

DSP(Digital Signal Processing,数字信号处理)中会使用大量的数学运算。Cortex-M4中,配置了一些强大的部件,以提高DSP能力。同时CMSIS提供了一个DSP库,提供了许多数学函数的高效实现。

这次就先做一个简单的尝试,求两个向量的数量积。

 

一、 硬件

image

  • MAC单元

    MAC(Multiply-ACcumulate,乘积累加),是DSP中常用的一种运算。Cortex-M4配置了一个32位的MAC单元,它能在1个周期里实现最高难度为32位乘32位再加64位的运算,或是两个16位乘16位的运算。Cortex-M4支持的MAC指令如下,这些指令都能在1个周期内完成:

    image

  • SIMD

    SIMD(Single Instruction Multiple Data,单指令多数据),可以提高DSP时的计算效率。这在Cortex-M3中不可用的。使用Cortex-M4的SIMD指令,可以在一个周期并行地完成4个8位数的加减,或是2个16位数的加减。

  • FPU

    FPU是Cortex-M4增加的可选的部件(SAM4E配备了FPU)。其实现了单精度的浮点数运算,包括一些MAC运算:

    image

 

二、 使用CMSIS的DSP库

CMSIS中,提供了一个DSP库。这里对DSP中常用的数学运算做了很高效的实现。而对于Cortex-M4,其实现也针对SIMD进行了优化。

CMSIS\Include文件夹中,头文件arm_math.h 声明了这些函数。而在CMSIS\Lib\GCC 中,有针对各平台编译好了的静态库文件。在CMSIS\DSP_Lib\Source 中,有DSP的实现源码。

而在使用arm_math.h 文件的过程中,需要根据目标平台预定义宏ARM_MATH_CM4ARM_MATH_CM3 ARM_MATH_CM0 。而若需要使用FPU,则需要在设备头文件(如sam4e16e.h)中将宏__FPU_PRESENT 的值定义为1。

在AS6中,默认已经添加了DSP的支持。

  1. 进入工程属性的toolchain选项卡,可以在ARM/GNU C Complier的Directories中选择编译时搜索头文件的路径。AS6在建立工程时,就会一些需要的头文件拷贝到工程目录下,同时做好了路径设置。比如AS6已经把arm_math.h 拷贝到下图中方框指出的路径了:

    image

  2. 在ARM/GNU Linker的Libraries选项中,可以选择链接时使用的库以及库的路径。同样,AS6已经把静态库文件拷贝到了工程目录下,且设置好了文件:

    image

  3. 在ARM/GNU C Complier的Symbols选项中,可以设置预定义的宏。可以在这里声明说明DSP的目标平台的宏ARM_MATH_CM4

    image

  4. 在设备头文件件中声明__FPU_PRESENT 的值。如果有FPU,则将该宏定义为1,否则定义为0。CMSIS已经做好了定义:

    //File: …src\ASF\sam\utils\cmsis\sam4e\include\sam4e16e.h
    
    //Line: 266
    
    /**< SAM4E16E does provide a FPU */
    
    #define __FPU_PRESENT          1

     

    另外,如果不使用AS6提供的startup文件,或者需要在自己的代码中使用FPU的话,还需要做额外的设置。相关内容在FPU的示例中做了说明。

 

三、 简单示例

DSP库里有计算向量数量积的函数。DSP库的函数支持多种类型的定点数,且对于配备了FPU的部件,也支持浮点数。所以只需要简单地调用下所需函数即可:

// 向量为(0.0, 1.1, 2.2, ..., 16.5)

const int VEC_SIZE = 16;

float32_t vec[VEC_SIZE];

for (int i = 0; i < VEC_SIZE; ++i)

	vec[i] = 1.1f * i;	

	

// 计算向量与自身的数量积

float32_t result = 0;

arm_dot_prod_f32(vec, vec, VEC_SIZE, &result);

// result == 1500.4

 

查看arm_dot_prod_f32() 的实现,发现其已经为了效率进行了循环展开。而查看另外一些有关定点数的运算,可以发现其实现已经使用了SIMD等特殊指令;有些甚至针对内存访问的延迟进行了优化。不难看出,这个库的实现进行了细致优化的。

另外,除了基本的数学函数,DSP库也实现了快速数学函数(三角函数、开平方等)、实数相关、矩阵运算、统计、滤波、变换(FFT等)、马达控制等功能。arm_math.h 中,已经对各个函数的功能、参数意义等做了详细的说明。

你可能感兴趣的:(单片机)