前回作成したLチカClassをHALに対応させる

前回 https://ioloa.com/?p=157 このページでLチカをしました。

前回はSTM32G4+LLという構成でLチカをしていますが、
STにはLLに非対応なマイコンもあります。

そこで今回は、GPIOCtrl.hppとGPIOCtrl.cppをほんの僅かに変更して、
STM32H7+HALで全ての機能が動くようにします。

以下、既にSTM32H7のプロジェクトがCubeMXを用いて吐かれてる状態から書きます。

①前回のソース
これが前回のソースです。

/*
 * GPIOCtrl.hpp
 *
 *  Created on: Sep 8, 2019
 *      Author: Nakamura(Yutaka)
 */

#ifndef GPIOCTRL_HPP_
#define GPIOCTRL_HPP_

#include "gpio.h"
#include "stm32g4xx_hal.h"

class GPIOCtrl {
public:
	enum GPIOStatus {
		GPIO_OFF = 0,
		GPIO_ON = 1,
	};

private:
	GPIO_TypeDef *mGPIOx;
	uint32_t mPinMask;
	GPIOStatus mGPIOStatus;
public:
	GPIOCtrl( GPIO_TypeDef *pGPIOx, uint32_t pPinMask );
	virtual ~GPIOCtrl();
	void ON();
	void OFF();
	void Toggle();
};

#endif /* GPIOCTRL_HPP_ */
/*
 * GPIOCtrl.cpp
 *
 *  Created on: Sep 8, 2019
 *      Author: Nakamura(Yutaka)
 */

#include "GPIOCtrl.hpp"

GPIOCtrl::GPIOCtrl( GPIO_TypeDef *pGPIOx, uint32_t pPinMask)
:mGPIOx(pGPIOx), mPinMask(pPinMask), mGPIOStatus(GPIO_OFF) {
	OFF();
}

GPIOCtrl::~GPIOCtrl() {
}

void GPIOCtrl::OFF() {
	mGPIOStatus = GPIO_OFF;
	LL_GPIO_ResetOutputPin(mGPIOx, mPinMask);
}

void GPIOCtrl::ON() {
	mGPIOStatus = GPIO_ON;
	LL_GPIO_SetOutputPin(mGPIOx, mPinMask);
}

void GPIOCtrl::Toggle() {
	if(mGPIOStatus) {
		OFF();
	} else {
		ON();
	}
}

②次のように変更する
以下のように変更します。

/*
 * GPIOCtrl.hpp
 *
 *  Created on: Sep 8, 2019
 *      Author: Nakamura(Yutaka)
 */

#ifndef GPIOCTRL_HPP_
#define GPIOCTRL_HPP_

#include "gpio.h"
//マイコンを変更したので利用するライブラリが変わる
//#include "stm32g4xx_hal.h" 
#include "stm32h7xx_hal.h" 

class GPIOCtrl {
public:
	enum GPIOStatus {
		GPIO_OFF = 0,
		GPIO_ON = 1,
	};

private:
	GPIO_TypeDef *mGPIOx;
	uint32_t mPinMask;
	GPIOStatus mGPIOStatus;
public:
	GPIOCtrl( GPIO_TypeDef *pGPIOx, uint32_t pPinMask );
	virtual ~GPIOCtrl();
	void ON();
	void OFF();
	void Toggle();
};

#endif /* GPIOCTRL_HPP_ */
/*
 * GPIOCtrl.cpp
 *
 *  Created on: Sep 8, 2019
 *      Author: Nakamura(Yutaka)
 */

#include "GPIOCtrl.hpp"

GPIOCtrl::GPIOCtrl( GPIO_TypeDef *pGPIOx, uint32_t pPinMask)
:mGPIOx(pGPIOx), mPinMask(pPinMask), mGPIOStatus(GPIO_OFF) {
	OFF();
}

GPIOCtrl::~GPIOCtrl() {
}

void GPIOCtrl::OFF() {
	mGPIOStatus = GPIO_OFF;
	HAL_GPIO_WritePin(mGPIOx, mPinMask, GPIO_PIN_RESET);
    //LLは用意されていないのでHALを利用する。
	//LL_GPIO_ResetOutputPin(mGPIOx, mPinMask);
}

void GPIOCtrl::ON() {
	mGPIOStatus = GPIO_ON;
	HAL_GPIO_WritePin(mGPIOx, mPinMask, GPIO_PIN_SET);
	//LL_GPIO_SetOutputPin(mGPIOx, mPinMask);
}

void GPIOCtrl::Toggle() {
	if(mGPIOStatus) {
		OFF();
	} else {
		ON();
	}
}

これだけです。
(内容が薄くてすいません。)
このように、システムの中核のClassをすこし変更すれば、
マイコンを変更しても対応できます。

やる気になれば、別のメーカーのマイコンへの移植も容易にできます。

STM32 CubeIDE環境で、CMSIS-DSPを使う方法

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\libarm_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に入れていますが、別のフォルダにパスを通して、ライブラリに必要なもの一式を入れると見やすくて良いかと思います。