2019年3月11日月曜日

STM32: CMSIS-DSPのFast Math Functionsの処理速度

CMSIS-DSPのFast Math Functionsの処理速度を測定しました。

CMSIS-DSP Fast Math Functions
http://www.keil.com/pack/doc/CMSIS/DSP/html/group__groupFastMath.html

CMSIS-DSPのFast Math Functionsは

  • Square Root
  • Cosine
  • Sine

の固定小数点数と単精度浮動小数点数の関数が用意されています。

使い方は「ガレスタさんのDIY日記」の「STM32でCMSIS DSPを使ってみる その1」を参考にしました。

実行環境

  • Nucleo-F446RE
  • STM32CubeMX Version 5.1.0
  • System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911

プロジェクト:
https://github.com/ryood/Nucleo_F446_FloatingPoint/tree/master/SW4STM32/floating_point_vsCMSIS_DSP_test1

CMSIS-DSPのライブラリファイルの準備


「<STM32Cube>\Repository\STM32Cube_FW_F4_V1.24.0\Drivers\CMSIS\Lib\GCC\libarm_cortexM4lf_math.a」を「<workspace>\CMSIS_DSP_test1\」(プロジェクトのルート)にコピー。


ファイル名の"l"はリトル・エンディアン、"f"はfpuの意味のようです。

インクルードファイルの準備


「<STM32Cube>\Repository\STM32Cube_FW_F4_V1.24.0\Drivers\CMSIS\DSP\Include\arm_math.h」を「<プロジェクトフォルダ>\Inc」にコピー

SW4STM32でビルドオプションを指定


GCC Linkerの設定で[Libraries (-l)]と[Library search path(-L)」を設定

Libraries(-l)
arm_cortexM4lf_math

Library search path(-L)
"${workspace_loc:/${ProjName}}"


Libraryの指定は、接頭辞の"lib"及び接尾辞の".a"を抜きます。(参考「Tutorial: Using the ARM CMSIS Library」の「Library」の項)

GCC Compiler - Preprocessorで「ARM_MATH_CM4」を指定。


「__FPU_PRESENT」はもともと定義されているようで、Preprocessorで指定すると「redefined」のアラートが出ます。

コード


"arm_math.h"をインクルード

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "math.h"
#include "arm_math.h"
/* USER CODE END Includes */

メインループで関数を使う

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
 volatile float fv = 0.0f;
 LL_GPIO_SetOutputPin(CHK1_GPIO_Port, CHK1_Pin);
 for (int i = 0; i < LOOP_N; i++) {
  fv += 0.01f;
  //buffer[i] = sqrtf(fv);
  //buffer[i] = sinf(fv);
  //buffer[i] = cosf(fv);
  //arm_sqrt_f32(fv, buffer + i);
  buffer[i] = arm_sin_f32(fv);
  //buffer[i] = arm_cos_f32(fv);
 }
 LL_GPIO_ResetOutputPin(CHK1_GPIO_Port, CHK1_Pin);
  }
  /* USER CODE END 3 */
}

math Libraryの関数(sinf()など)と、CMSIS-DSPの関数(arm_sqrt_f32()など)をコメントアウトしたり外したりしてビルドし直して計測しました。GPIOをH/Lさせてオシロで処理時間を測定しました。GPIO操作には低レベルAPIのLL APIを使用しました。(参考「GPIO出力の速度比較 mbed OS5 vs HAL API vs LL API」)

コンパイラ・オプション

-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DUSE_FULL_LL_DRIVER -DARM_MATH_CM4 -D__weak=__attribute__((weak)) -D__packed=__attribute__((__packed__)) -DUSE_HAL_DRIVER -DSTM32F446xx -I../Inc -I../Drivers/STM32F4xx_HAL_Driver/Inc -I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32F4xx/Include -I../Drivers/CMSIS/Include -O2 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -fmessage-length=0

リンカ・オプション

-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -L"D:\Users\gizmo\Documents\workspace\floating_point_vsCMSIS_DSP_test1" -specs=nosys.specs -specs=nano.specs -T"../STM32F446RETx_FLASH.ld" -Wl,-Map=output.map -Wl,--gc-sections -lm

ビルドすると、「arm_sqrt_f32(fv, buffer + i);」でvolatile修飾に対して警告が出ましたが無視しています。

警告メッセージ

Description Resource Path Location Type
passing argument 2 of 'arm_sqrt_f32' discards 'volatile' qualifier from pointer target type [-Wdiscarded-qualifiers] main.c /floating_point_vsCMSIS_DSP_test1/Src line 112 C/C++ Problem

Debugパースペクティブの式の評価(arm_sin_f32())


測定結果


測定データ

op math(us) CMSIS-DSP(us)
sqrt 178 194
sine 1038 345
cosine 1002 345

sine, cosineはCMSIS-DSPを使うとかなり高速化できるようです。

メモ:


STM32CubeMXとSW4STM32を行ったり来たりすると、「STM32F446RETx_FLASH.ld」が空(0Byte)になってビルドできなくなることがあります。「STM32F446RETx_FLASH.ld」を削除してSTM32CubeMXでGenerate Codeし直せば良いようです。

0 件のコメント:

コメントを投稿