查看: 4217|回复: 3

[CodeWarrior] 移植CMSIS-DSP库到CodeWarrior的步骤以及Kinetis FPU单元应用的对比

[复制链接]

该用户从未签到

656

主题

6312

帖子

0

超级版主

Rank: 8Rank: 8

积分
20028
最后登录
2024-4-26
发表于 2017-9-29 11:26:03 | 显示全部楼层 |阅读模式
本帖最后由 小恩GG 于 2017-9-29 11:27 编辑

移植CMSIS-DSP库到CodeWarrior的步骤以及Kinetis FPU单元应用的对比                                                     FAE Const Yu

      在电机控制,Audio等很多应用中,我们经常会用到一些常见的正余弦,矩阵变换,FFT等一些DSP函数,提到DSP库,通常会想到使用ARM 公司提供的 CMSIS 库。CMSIS 库是ARM和一些半导体厂家针对Cortex-M系列制定的一套接口标准,包括针对内核操作的CMSIS-CORE API,针对DSP应用的CMSIS-DSP Library,针对RTOS的CMSIS-RTOS API,与外设接口的CMSIS-SVD以及提供Debug访问接口的CMSIS-DAP。 其中,又以DSP应用的CMSIS-DSP 库的应用最为广泛。针对Cortex-M4中的DSP功能,CMSIS-DSP部分提供了超过60多种功能的DSP算法库,尤其是随着Cortex-M4中集成了FPU硬件单元,CMSIS-DSP 库的应用也越来越广泛。
   在KEIL 和IAR中都集成了对CMSIS的支持,然而在CodeWarrior中没有直接支持CMSIS,需要用户移植到自己的CW工程中,所以就需要使用者了解CMSIS的结构,手动添加库文件和头文件,并完成一些重要的编译参数配置。特别是有些芯片支持FPU浮点运算单元,有些不支持,在配置选项上差别很大。在飞思卡尔Kinetis系列芯片中,FPU浮点运算单元也是一个可选的部件,只有在名称中带有FN和FX的芯片才支持FPU硬件浮点功能,如MK60FN1M0, MK60FX512。本文档分别介绍在使用和不使用FPU的情况下如何一步步移植CMSIS的DSP库到自己的CodeWarrior工程中。
      需要注意的是 FPU 单元是指的芯片上的一个独立于 CPU 处理的浮点运算单元,整个单元在大多数厂家的芯片中都是可以被使能和关闭的。相对于芯片,编译器也设置了相应的 FPU 功能开启/关闭的选项,在编译时需要告诉编译器是否开启 FPU 功能。编译器一旦开启 FPU 功能,在处理单精度浮点运算的语句时就会用带 V-开头的汇编指令进行编译。如果编译器使能了 FPU 功能,而芯片未开启 FPU 单元,程序运行到浮点语句时就会出现异常。相反,如果编译器未使能 FPU 功能,芯片即使开启了 FPU单元,程序还是会按照未使能 FPU 的代码进行处理。在本例程中,为对比分析是否采用FPU的编译指令差别以及在板的执行效率,选用Kinetis K70FN1M为实验对象。
硬件平台:TWR-K70F120M核心板      软件环境:CodeWarrior v10.5        CMSIS版本 :V3.2
一. 准备工作:
      下载CMSIS的库,当前最新的版本为V3.2,解压后名称为CMSIS-SP-00300-r3p2-00rel1,其目录结构如下图。分别包含CMSIS-DSP, CMSIS-RTOS和CMSIS-SVD的库文件。在本Cortex M4的CMSIS-DSP的应用中,真正用到的文件包括CMSIS\Include中CM4相关的头文件,CMSIS\Lib\GCC文件夹中的库文件libarm_cortexM4l_math.a(软浮点)和libarm_cortexM4lf_math.a(硬浮点),以及Device\ARM\ARMCM4\include中外设访问相关的两个头文件。
1.jpg
二. 不使用K70的FPU浮点运算单元,移植CMSIS的DSP库到CW的步骤;

     Step 1:    新建一个Baremental的工程,选择器件器件MK70FN1M0(支持硬件FPU);
2.jpg
     Step 2:    选择Floating Point浮点运算实现的类型,即指定编译器将C代码编译成汇编代码时使用的规则;
3.jpg
在Floating Point四个选项含义如下:



    • Software选项:表示不使用FPU硬件,而是使用GCC的整数算术运算来模拟浮点运算;
    • Handware(-mfloat –abi=hard) 选项:表示使用FPU硬件来进行浮点运算,函数的参数直接传递到FPU的寄存器(s0-d0)中;
    • Handware(-mfloat –abi=softfp)选项:表示使用FPU硬件来进行浮点运算,但是函数的参数传递到整数寄存器(r0-r3)中,然后再传递到FPU中;
    • Handware(-mfloat –abi=softfp –fshort -double)选项:其配置项同上,只不过使能了fshort  double功能,并且此处的double数据的宽度等同于float;
有兴趣研究各个选项意义的可以参考[url=]CW for MCU技术文档[/url]的第3章,在本例程中使用的是软浮点,所以选择Software项。需要注意的是:此配置选项仅出现支持FPU硬件单元的芯片工程中,如MK60FN1M0, MK60FX512等,否则默认没有此选项,默认为软件浮点。
Step 3:    点击“Next”进入下图,选择使用Processor Expert,点击“Finish“完成工程的建立;
4.jpg
Step 4:    进入当前工程的文件夹,新建文件夹CMSIS,从之前在准备步骤解压的CMSIS文件包\...\CMSIS-SP-00300-r3p2-00rel1\CMSIS中拷贝Include和Lib文件夹到当前工程新建的CMSIS文件夹。另外,拷贝\...\CMSIS-SP-00300-r3p2-00rel1\Device\ARM\ARMCM4\Include中的ARMCM4.h和system_ARMCM4.h到当前工程新建的CMSIS文件夹中;
5.jpg

Step 5:    回到CodeWarrior主界面选择新建的工程文件,F5刷新可以看到CMSIS出现在工程文件中。其中Include是CMSIS库的一些头文件,包括M0+/M3/M4的一些头文件;在Lib文件中是已经编译好的库文件,ARM文件夹是使用在KEIL IDE中的库文件,G++文件夹是使用在IAR中的库文件,而由于当前CW工程使用的GCC的编译器,所以GCC文件夹才是CW需要的,因此,为缩减工程大小可以删除ARM和G++文件夹;
6.jpg
     Step 6:    打开工程属性框,选择Target Processor的Float ABI为No FPU;
7.jpg
Step 7:    在GCC Complier的Defined symbols中添加编译的宏定义ARM_MATH_CM4;
8.jpg
Step 8:    在GCC Complier的Include paths中添加CMSIS库的头文件,路径为:工程目录\CMSIS\Include;
9.jpg
Step 9:    在GCC C Linker的Miscellaneous项的Other objects中指定使用的库文件(位于CMSIS\Lib\GCC文件夹中)。因为本例程中不使用FPU,所以选择libarm_cortexM4l_math.a,此处需要特别注意,否则编译会报错;
10.jpg
Step 10: 在ProcessorExpert.c文件中添加代码;
#include <math.h>
#include "arm_math.h"

#define DELTA    (0.000001f)

const float32_t testRefOutput_f32 = 1.000000000;
const float32_t radians=1.047197533333333;

float32_t  cosOutput, sinOutput, diff;
float32_t cosSquareOutput,sinSquareOutput,testOutput;

int main(void)
{
  int m,n;
  PE_low_level_init();

  cosOutput = arm_cos_f32(radians); /*求正余弦*/
                  sinOutput = arm_sin_f32(radians);

                  arm_mult_f32(&cosOutput, &cosOutput, &cosSquareOutput, 1); /*求积运算*/
  arm_mult_f32(&sinOutput, &sinOutput, &sinSquareOutput, 1);

arm_add_f32(&cosSquareOutput, &sinSquareOutput, &testOutput, 1); /*求和运算*/
  diff = fabsf(testRefOutput_f32 - testOutput);  /* 求绝对值 */

  if(diff > DELTA)
  {
                        while(1)
                                {
                                  for(m=0;m<2000;m++)
                                                for(n=0;n<200;n++){};
                                                D7_NegVal();
                                }
    }
                }
Step 11:    编译并下载Debug,在  sinOutput = arm_sin_f32(radians);处设置断点,可以看到CMSIS-DSP库中的正余弦浮点数运算函数运算正常,其反汇编的得到为普通的ARM指令(FPU 单元汇编指令通常在普通指令前加字母V,仅在 FPU 功能被使能时使用),完成一个正弦计算;
11.jpg
至此,完成了不使用K70的FPU浮点运算单元,移植CMSIS的DSP库到CW的步骤。

    三.     使用K70的FPU浮点运算单元,移植CMSIS的DSP库到Codewarrior的步骤

使用K70的FPU硬件浮点运算单元,移植CMSIS的DSP库到Codewarrior的方法有两种:一种是按照上面软浮点的方式Step By Step的建立工程,步骤和上面二的步骤基本一致,主要的两个区别在于:(1). Step 2要选择Handware(-mfloat –abi=hard) 选项,(2). Step 9 改为libarm_cortexM4lf_math.a。另外一种就是在上面工程的基础上修改配置选项。鉴于方便,本教程采用第二种方案,完成在Codewarrior中调用CMSIS的DSP库,通过K70的FPU浮点运算单元执行浮点运算,即硬浮点。
Step 1:    打开工程属性对话框,选择Target Processor的Float ABI为FPU with hard vfp passing(-mfloat –abi=hard);
12.jpg
Step 2:    在GCC Complier的Defined symbols中添加编译的宏定义:_VFPV4;
13.jpg

Step 3: 在GCC C Linker的Libraries项的library search path中指定链接的规则,把上面工程中默认的"${MCUToolsBaseDir}/ARM_GCC_Support/ewl/lib/armv7e-m"修改为 "${MCUToolsBaseDir}/ARM_GCC_Support/ewl/lib/armv7e-m/fpu";
14.jpg
Step 4:    在GCC C Linker的Miscellaneous项的Other objects中指定使用的库文件(位于CMSIS\Lib\GCC文件夹中)。因为本例程中使用FPU,所以选择libarm_cortexM4lf_math.a,此处需要特别注意,否则编译会报错;
15.jpg
Step 5:    完成以上配置后,编译工程并下载调试(此处建议编译之前先Clean一下整个工程),同样,在  sinOutput = arm_sin_f32(radians);处设置断点,可以看到CMSIS-DSP库中的正余弦浮点数运算函数运算正常,其反汇编的得到为FPU指令(FPU指令通常是指在普通指令前加字母V,仅在 FPU功能被使能时使用),并且在Register观察窗口中也多了个FPU寄存器列表,感兴趣的读者可以对比一下和前面实验汇编出代码的差异,此处不再赘述;
16.jpg
      至此,分别完成了使用和不适用K70的FPU浮点运算单元情况下, CMSIS的DSP库到Codewarrior的移植。在实际应用中需要用到更多的DSP函数,在项目中直接调用即可。下一步, Just Enjoy The Convenience of  The CMSIS!
有一点需要说明的是,前文中讲到使用FPU单元需要两步设置:(1). 在编译器中开启相应的 FPU 功能选项;(2). 开启芯片FPU 单元。似乎我们前面的设置是完成了第一个步骤,然而第二个步骤呢?仔细查看_arm_atart.c文件,可以发现代码_fp_init()正是完成了开启芯片FPU单元的过程,如下图,是一个条件编译函数,这也就解释了为什么在上面Step 2中定义了_VFPV4,其本质也就是使能芯片的FPU单元,其具体实现可以查看ARM手册的第74页的描述。
#ifdef   __VFPV4__        //Step 2中的宏定义
                __fp_init();      // 开启芯片的FPU单元
#endif



我知道答案 目前已有3人回答
回复

使用道具 举报

  • TA的每日心情
    开心
    2019-2-11 11:14
  • 签到天数: 345 天

    [LV.8]以坛为家I

    18

    主题

    1317

    帖子

    4

    金牌会员

    Rank: 6Rank: 6

    积分
    3096
    最后登录
    2023-3-16
    发表于 2017-9-29 14:15:23 | 显示全部楼层
    谢谢,分享!!!
    回复

    使用道具 举报

  • TA的每日心情
    开心
    昨天 12:01
  • 签到天数: 819 天

    [LV.10]以坛为家III

    71

    主题

    2445

    帖子

    24

    金牌会员

    Rank: 6Rank: 6

    积分
    5518
    最后登录
    2024-4-26
    发表于 2017-9-30 13:04:50 | 显示全部楼层
    感谢分享
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-9-15 08:42
  • 签到天数: 1952 天

    [LV.Master]伴坛终老

    1

    主题

    4686

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9405
    最后登录
    2023-9-15
    发表于 2017-9-30 20:22:17 | 显示全部楼层
    谢谢分享!
    今天天气不错!签到!
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-26 14:12 , Processed in 0.138248 second(s), 25 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表