Arm社が提供するCMSIS-DSP Libraryを利用すると、簡単に高速な演算ができます。
できることは、三角関数や平方根だけに留まらず、行列操作、FIRフィルタ・FFT、PIDコントローラ、クラーク変換・パーク変換等、幅広く入っています。
導入することで利用できる関数は以下のページにまとめられています。
https://www.keil.com/pack/doc/cmsis/dsp/html/modules.html
さて、このCMSIS-DSPですが、故・TrueStudioでの環境構築は、わかりやすくまとめられておりますが、CubeIDEでは少し操作する項目が増えておりますのでまとめてみます。
以下、執筆時の環境です。
IDE STM32CubeIDE Version: 1.0.0 Build: 2872_20190423-2022 (UTC) マイコン STM32F446RE
①ライブラリの追加 STM32Cubeのディレクトリから以下の2ファイルをコピーします。
STM32Cube\Repository\STM32Cube_FW_F4_Vxxxx\Drivers\CMSIS\Lib\ARM\arm_cortexM4lf_math.lib STM32Cube\Repository\STM32Cube_FW_F4_Vxxxx\Drivers\CMSIS\Lib\GCC\lib arm_cortexM4lf_math.a
これらをプロジェクトフォルダ内にコピーします。
Windows環境でしたらユーザフォルダ内にSTM32Cubeがあるかと思います。 またVxxxxは適宜読み替えてください。
②プロジェクトファイルの設定 CubeIDEの (プロジェクトのプロパティ)>C/C++Build>Setting>ToolSettings>MCU G++ >Linker>Libraries の設定で以下の2項目を登録します。 1.Libraries>addから、arm_cortexM4lf_mathを登録 2.Library search path>add>workspace… から、 (先程arm_cortexM4lf_math.aをコピーしたディレクトリ)を選択します。 正しく指定できていれば、 ${workspace_loc:/${ProjName}} となるはずです。
Tips ファイル名のM4lf_mathのlfはLittle endian,fpuの略。 つまり、M4l_mathやM4b_math(Big endian)のfpuなしのmathライブラリは使う機会があるのか疑問。 また、M7系の上位マイコンでは、 arm_cortexM7lfdp_mathのような(double precision)を扱えるものもある。
③Includeをする 関数を使いたい.c/.cppファイルにて、以下を定義してIncludeします。
#define ARM_MATH_CM4
#include "arm_math.h"
#include "arm_const_structs.h"
定義しているCM4はCortex-M4の略で、 CortexM7→CM7 CortexM4→CM4 CortexM3→CM3 CortexM0→CM0 とマイコンボードによって変更します。 以後、今回利用するCortexM4のみ解説するので、 別のCPUの時は適宜読み替えてください。
③足りないものを追加する 試しにこの段階でビルドしてみましょう。 次のような怒られが発生するはずです。
../Src/main.c:24:10: fatal error: arm_math.h: No such file or directory
#include "arm_math.h"
^~~~~~~~~~~~
(以前のTrueStudio環境では、この段階で勝手に足りないものを取ってきてくれて、ビルドが通った記憶があります。) いろいろ足りないので、必要なファイルをIncに追加します。
STM32Cube\Repository\STM32Cube_FW_F4_Vxxxx\Drivers\CMSIS\DSP\Include 内にある、arm_math.h arm_const_structs.h arm_common_tables.h をインクルードできる場所に追加します。 (例えばプロジェクト内のInc)
以上の操作にて、CMSIS-DSPのライブラリが利用できるようになります。 試しに以下のようにmainの内部を変更して、コードを実行してみます。
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#define ARM_MATH_CM4
#include "arm_math.h"
#include "arm_const_structs.h"
/* USER CODE END Includes */
/* USER CODE BEGIN WHILE */
int num = 0;
while (1)
{
float armsinVal = arm_sin_f32((float32_t)num*2*M_PI/255);
float armcosVal = arm_cos_f32((float32_t)num*2*M_PI/255);
float sinVal = sin((float)num*2*M_PI/255);
float cosVal = cos((float)num*2*M_PI/255);
num++;
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
ブレークポイントを打って実行をすると、以下のように動作の確認ができるかと思います。
今回は手抜きをしたのでタイマを動かして動作時間の解析等はしませんでしたが、 タイマを動作させて実行時のタイマ値を読んだりすると面白いかと思います。
Tips 今回は説明の便宜上、必要なものを全てプロジェクトフォルダやIncに入れていますが、別のフォルダにパスを通して、ライブラリに必要なもの一式を入れると見やすくて良いかと思います。