概要
STマイクロエレクトロニクスが無償で提供しているFFTサンプルコードを、別の記事(関連記事の2 )で紹介しましたが、その対象となるボード(STEVAL-BFA001V2B1)が、IO-Linkデバイスを搭載した少し特殊な評価ボードでした。
そこで、サンプルコードを汎用的な評価ボード:STEVAL-STWINBX12で試せるように移植(ポーティング)をしましたので、今回、その内容を一例として紹介します。
●ボードの違い:
まず、ボードの違いを見てみましょう。下のブロック図は、サンプルコードに関わる箇所のみを表しています。
2つのブロック図を見比べると、加速度センサは同じですが、STM32マイコンは、STM32F469からSTM32U585の比較的新しい製品に変更となります。また、加速度センサからの割り込み入力の数も異なります。
●ソフトウェア変更内容の概略
移植元のサンプルコードの構成は下図のようになっています。必要な変更箇所は、主にマイコンの製品シリーズに依存した、ドライバ層とそれを使用した初期化コードなどになります。
そこで今回は、下図のように、初期化コード生成ツール:STM32CubeMX と評価ボード用サンプルコード を活用し、面倒なソースコードの記述による変更を減らす形で移植を行いました。
作業としては、次のような流れで移植を進めました。
0.準備
1.初期化コードの自動生成
2.必要なソースファイルのコピー
3. ファームウェアプロジェクトの設定
4. ソースコードの一部を修正
最後にビルドして動作確認する簡単な手順を示してあります。
0ー準備
まず、以下の必要なものを準備します。今回使用したバージョンを括弧内[]内に示してあります。
[ STM32マイコン開発ツール ]
・STM32初期化コード生成ツール : STM32CubeMX [Ver.6.15.0]
・STM32マイコン用開発IDEツール:STM32CubeIDE [Ver.1.19.0]
[ サンプルコードと評価ボード ]
・移植するサンプルコードを含むソフトウェアパック:FP_IND_PREDMNT1[Ver.2.4.1]3
・移植に利用可能なコードを含むソフトウェアパック:FP_SNS_DATALOG2[Ver.3.1.0]4
・移植先の評価ボード:STEVAL-STWINBX1ボード2
1ー初期化コードの自動生成
STM32CubeMXを使用して、初期化コードを含むをFWプロジェクトを生成します。
以下、STM32CubeMXの設定内容です。
(1) プロジェクトを新規作成
STM32CubeMx起動後の表示画面にある "ACCESS TO BOARD SELECTOR" のボタンからSTEVAL-STWINBX1を選択して、新規プロジェクトを開きます
(2) Clockの設定
① [Pinout & Configurationタブ] ― (RCC)のMode設定:
・外部オシレータ(HSE)を有効
② [Clock Configurationタブ]の設定:
・PLL SourceをHSEに設定し、システムクロックを160MHzに設定
Clock設定画面の図( ここをクリックすると展開します )
(3) 周辺機能の設定 [Pinout & Configurationタブ]
① SPI2の設定
加速度センサのSPI I/Fは、SPI mode-0とmode-3に対応しています。ここではmode-3に設定しています。
③ USART2の設定
・PCの端末ソフト(TeraTermなど)との通信設定
( Asynchronousモード、230400bpsのボーレートに設定 )
④ GPDMA1の設定
・(CH0の設定) : 一般的なDMAモード(Standard Request mode)を使用し、メモリ領域からUSART2のデータレジスタへの転送設定
・(CH1の設定) : 一般的なDMAモード(Standard Request mode)を使用し、USART2のデータレジスタからメモリ領域への転送設定
⑤ 割り込みの設定
加速度センサ用の外部割り込みとUARTの割り込みを有効
⑥ その他の設定
・内蔵電源レギュレータの設定
マイコンに内蔵されている電源レギュレータは、SMPSに設定
・命令キャッシュ(ICACHE)の設定
STM32U5にはCPUの命令アクセス速度を向上させるための命令キャッシュの機能の設定。ここでは標準的なモードに設定。
周辺機能設定画面の図はここをクリックすると開きます
●SPI2の設定
・[Mode]と[Configuration]-[Paramter Settings]

CPOL:Highの場合、GPIOの設定でPull-Upの設定が必要です。
・[Configuration]-[GPIO Settings]
(4) 加速度センサのソフトウェアコンポーネンツを追加・設定
① SoftwarePacksからソフトウェアコンポーネンツを追加
② X-CUBE-MEMS1の設定
Board Part Accにチェックをして、Platform Settings のタブの中の項目を設定
(5) プロジェクトの生成 [Project Managerタブ]
- STM32CubeIDE用FWプロジェクトの設定とリンカーの設定
- 生成コードの設定
- [GENERATE CODE] ボタンをクリックしてFWプロジェクトを生成
プロジェクトの設定画面の図はここをクリックすると開きます
●STM32CubeIDE用FWプロジェクトの設定とリンカーの設定

●生成コードの設定

● [GENERATE CODE] ボタンをクリック

生成されると下図のようなフォルダー構成になります。
これでSTM32CubeMXを使用した初期化コードの生成作業は完了です。
2ー必要なソースファイルをプロジェクトフォルダにコピー
(1)フォルダ単位でコピーするソースファイル
① FP_SNS_DATALOG2から以下のフォルダをコピー
・[BSP]-[STWIN.box]フォルダ
・[BSP]-[Components]-[Common]フォルダ
② FP_IND_PREDMNT1から以下のフォルダをコピー
・[STM32_MotionSP_Library]フォルダ
③ STM32Cube_FW_U5から以下のフォルダをコピー
ここではDSPというフォルダを作成し、そこにコピーします。
・[Drivers]-[DSP]-[Include]フォルダ
・[Drivers]-[DSP]-[PrivateInclude]フォルダ
・[Drivers]-[DSP]-[Source]フォルダ
(3)STWIN.box_conf_temp.hのファイル名を変更
FP_SNS_DATALOG2ソフトウェアパックの[Drivers]-[BSP]-[STWIN.box]フォルダにあるSTWIN.box_conf_temp.hのファイル名を、STWIN.box_conf.h に変更。
3ーファームウェアプロジェクトの設定
ここからは、STM32CubeMXで生成したSTM32CubeIDEのFWプロジェク上で操作を行います。
(1) 必要なソースファイルをSTM32CubeIDEのプロジェクトにインポート
上でコピーしたソースファイルをSTM32CubeIDEにインポート(Import)します。
(2) Includeファイルのパスを設定
先ほどコピーしたヘッダーファイルのパスを設定します。
FWプロジェクトの開き方や、インポートの仕方、インクルードパスの設定方法に関しては、関連記事の1 を参考にしてください。
インポート後の状態とインクルードファイルの設定内容は、以下のようになります。

(3) 不要なファイルをCubeIDEから削除
今回のサンプルコードでは使用しないファイルや、関数などの定義が重複するファイルなどを削除します。下表に削除するファイル名をリストにしました。
*)CMSIS-DSPライブラリのソースファイルに関しては、削除するファイル数を少なくする形にしています。実際にはコードの中で使用している必要なAPIの定義があるファイルのみにすることも可能です。
(4) その他の設定
①今回のサンプルコードでは、printf関数にfloat型のデータを使用しているため、次のオプションを有効にします。
② CMSIS-DSPライブラリを使用しているので、最適化を次のように設定します。

4ーソースコードの一部を修正
以下、ファイル毎に、コード修正が必要な箇所を記載しました。そのほとんどが、移植元のソースコードからのコピペと簡単な修正です。
[Source files]
main.c 変更点(ここをクリックすると展開)
- 移植元のmain.cのソースコードの必要な箇所をコピペ。
- HAL_GPIO_EXTI_Rising_Callbackのコールバック関数のみ、新たなコードの追加が必要。これはマイコンに接続される加速度センサからの割り込み入力が1つのみとなったため、変数のフラグによる場合分けのコード。FP_IND_PREDMNT1の以下のサンプルコードを参考に変更。
[ STM32CubeFunctionPack_PREDMNT1_V2.4.1\Projects\STM32L4R9ZI-STWIN\Demonstrations\Predictive_Maintenance_BLE ]
STM32CubeMXを使用して生成されたファイルに関しては、/* USER CODE BEGIN xxx */ と /*USER CODE END xxx */の間にユーザーコードを記載します。それ以外のところに記載したコードは、STM32CubeMXでコードを再生成した際に、それらは消えてしまいますので、ご注意ください。
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
//(1)追加 ここから
#include <stdio.h>
#include "TargetFeatures.h"
//(1)追加 ここまで
/* USER CODE END Includes */
:
:
/* USER CODE BEGIN PV */
//(2)追加
extern uint8_t FifoEnabled;
/* USER CODE END PV */
:
:
int main(void)
{
:
:
/* USER CODE BEGIN 2 */
//(3)追加
InitTargetPlatform(TARGET_BFA001V2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//(4)追加
if (MotionSP_MainManager() != BSP_ERROR_NONE) Error_Handler();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
:
:
:
/* USER CODE BEGIN 4 */
//(5)追加 ここから
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case INT1_DWB_Pin:
if(FifoEnabled)
MotionSP_FifoFull_IRQ_Rtn();
else
MotionSP_DataReady_IRQ_Rtn();
break;
default:
break;
}
}
//(5)追加 ここまで
//(6)追加 ここから
/**
* @brief Get MCU Info
* @details See "MCU device ID code" paragraph into the MCU Reference Manual
* @param pMcuInfo Pointer to the MCU ID structure to be filled
* @return None
*/
void Get_McuInfo(sMcuInfo_t *pMcuInfo)
{
uint16_t pkg_bit = 0; /* see MCU Reference manual */
uint16_t pkg_nbit = 0; /* see MCU Reference manual */
if (pMcuInfo != NULL)
{
/* Read the device Id code */
pMcuInfo->idcode.value = DBGMCU->IDCODE;
switch(pMcuInfo->idcode.fileds.devid)
{ /* see AN2606 */
case 0x434:
strncpy(pMcuInfo->devicename, "STM32F469xx/479xx", 24);
pkg_bit = 8;
pkg_nbit = 3;
break;
case 0x470:
strncpy(pMcuInfo->devicename, "STM32L4Rxx/4Sxx", 24);
pkg_bit = 0;
pkg_nbit = 5;
break;
default:
strncpy(pMcuInfo->devicename, "Unknown", 24);
break;
}
/* Read the unique device ID registers (96 bits) */
for (uint8_t i=0; i<3; i++)
pMcuInfo->udevid.value[i] = *((uint32_t *)(UID_BASE+(i*sizeof(uint32_t))));
/* Read the size of the device Flash memory expressed in Kbytes */
pMcuInfo->flashsize = *((uint16_t *)(FLASHSIZE_BASE));
/* Read the package data */
pMcuInfo->package = (uint8_t)(((*((uint16_t *)(PACKAGE_BASE)))>>pkg_bit)&((1<<pkg_nbit)-1));
switch(pMcuInfo->idcode.fileds.devid)
{ /* see Reference Manual */
case 0x434:
switch(pMcuInfo->package)
{
case 0x4:
case 0x5:
strncpy(pMcuInfo->packagename, "LQFP208 or TFBGA216", 64);
break;
case 0x2:
strncpy(pMcuInfo->packagename, "LQFP176 or UFBGA176", 64);
break;
case 0x1:
strncpy(pMcuInfo->packagename, "WLCSP168 or UFBGA169", 64);
break;
default:
strncpy(pMcuInfo->packagename, "Reserved", 64);
break;
}
break;
case 0x470:
switch(pMcuInfo->package)
{
case 0x02:
strncpy(pMcuInfo->packagename, "LQFP100 without DSI", 64);
break;
case 0x03:
strncpy(pMcuInfo->packagename, "UFBGA132 without DSI", 64);
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
strncpy(pMcuInfo->packagename, "LQFP144 without DSI", 64);
break;
case 0x10:
strncpy(pMcuInfo->packagename, "UFBGA169 without DSI", 64);
break;
case 0x12:
strncpy(pMcuInfo->packagename, "LQFP100 with DSI", 64);
break;
case 0x13:
strncpy(pMcuInfo->packagename, "UFBGA144 with DSI, WLCSP144 with and without DSI", 64);
break;
case 0x14:
strncpy(pMcuInfo->packagename, "UFBGA169 with DSI", 64);
break;
case 0x15:
strncpy(pMcuInfo->packagename, "LQFP144 with DSI", 64);
break;
default:
strncpy(pMcuInfo->packagename, "Reserved", 64);
break;
}
break;
default:
break;
}
}
}
//(6)追加 ここまで
/* USER CODE END 4 */
MotionSP_Manager.c 変更点(ここをクリックすると展開)
・ヘッダファイルの変更と追加
・割り込み端子数減少に伴う変更(FifoEnabledフラグの追加と割り込み端子の変更)
//(1)削除 ここから
//#include "bfa001Vx_motion_sensors.h"
//#include "bfa001Vx_motion_sensors_ex.h"
//(1)削除 ここまで
//(2)追加 ここから
#include "STWIN.box_motion_sensors.h"
#include "STWIN.box_motion_sensors_ex.h"
#include "STWIN.box_errno.h"
//(2)追加 ここまで
/** @defgroup STM32_MOTIONSP_MANAGER_PRIVATE_VARIABLES MotionSP Manager Private Variables
* @{
*/
:
static uint16_t accCircBuffIndexForFftDelta = 0;
static uint8_t accCircBuffIndexForFftOvf = 0;
//(3)追加
uint8_t FifoEnabled=0;
:
:
:
static int32_t MotionSP_AcceleroFifoConfig(void)
{
:
/* Set FIFO mode */
if ((BSP_Error = BSP_MOTION_SENSOR_FIFO_Set_Mode(ACCELERO_INSTANCE, ACCELERO_FIFO_STREAM_MODE)) != BSP_ERROR_NONE)
return BSP_Error;
//(4)追加
FifoEnabled=1;
/* IIS3DWB INT2_FIFO_FULL interrupt enable */
//(5)変更:INT2をINT1に変更
if ((BSP_Error = BSP_MOTION_SENSOR_FIFO_Set_INT1_FIFO_Full(ACCELERO_INSTANCE, ENABLE)) != BSP_ERROR_NONE)
return BSP_Error;
:
:
}
static void MotionSP_FrequencyDomainAnalysis(void)
{
:
if (accCircBuffIndexTmp >= accCircBuffIndexForFftTmp)
{
if ((BSP_GetTick() - StartTick) > MotionSP_Parameters.tacq)
{
MotionSP_Running = 0;
FFT_avg = 1;
//(6)追加
FifoEnabled=0;
}
:
}
}
console.c 変更点(ここをクリックすると展開)
・UARTハンドラの定義と_read関数を定義
//(1)追加 ここから
extern UART_HandleTypeDef huart2;
#define hSrvUart huart2
//(1)追加 ここまで
//(2)追加 ここから
int _read(int file, char *ptr, int len)
{
*ptr = __io_getchar();
return 1;
}
//(2)追加 ここまで
TargetPlatform.c 変更点(ここをクリックすると展開)
・UART初期化関数のコール先を、CubeMX生成の関数に変更
//(1)追加 ここから
#include "STWIN.box.h"
#define USER_LED LED_GREEN
//(1)追加 ここまで
void InitTargetPlatform(TargetType_t BoardType)
{
TargetBoardFeatures.BoardType = BoardType;
#ifdef PREDMNT1_ENABLE_PRINTF
/* UART Initialization */
//(2)削除 ここから
/*
if(UART_Global_Init() != HAL_OK)
{
Error_Handler();
}
else
*/
//(2)削除 ここまで
//(3)追加
MX_USART2_UART_Init();
{
PREDMNT1_PRINTF("\033[%dm", BG_BLACK);
:
data_communication_srv.c(ここをクリックすると展開)
・UARTハンドラの宣言と定義
・printfによる画面表示内容の変更
//(1)追加 ここから
extern UART_HandleTypeDef huart2;
#define SRV_UART USART2
#define hSrvUart huart2
//(1)追加 ここまで
:
PREDMNT1_PRINTF("\033[%dm", FG_CYAN);
//(2)変更(F4をU5に変更)
PREDMNT1_PRINTF("\r\nSTM32U5xx Libraries & IDE informations:\r\n");
STWIN.box.c 変更点(ここをクリックすると展開)
・重複定義のためコメントアウト//(1)削除 ここから
/*
int __io_putchar (int ch)
{
(void)HAL_UART_Transmit(&hcom_uart[COM_ActiveLogPort], (uint8_t *)&ch, 1, COM_POLL_TIMEOUT);
return ch;
}
*/
//(1)削除 ここまで
[Header files]
main.h 変更点(ここをクリックすると展開)
・sMcuInfo_tの定義とGet_McuInfo関数の宣言(移植元からのコピペ) :
:
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
// (1)追加 ここから
/**
* @brief MCU identifiers
*/
typedef struct
{
union idcode_u
{
uint32_t value;
struct idcode_s
{
uint32_t devid: 12; //!< Device identifier
uint32_t res: 4;
uint32_t revid: 16; //!< Revision identifier
} fileds;
} idcode;
char devicename[24]; //!< Device name
union uniquedeviceid_u
{
uint32_t value[3];
struct udevid_s
{
uint32_t udevid_31_0; //!< 31:0 unique ID bits
uint32_t udevid_63_32; //!< 63:32 unique ID bits
uint32_t udevid_95_64; //!< 95:64 unique ID bits
} fields;
} udevid;
uint16_t flashsize; //!< The size of the device Flash memory expressed in Kbytes
uint16_t package; //!< Package data
char packagename[64]; //!< Package name
} sMcuInfo_t;
// (1)追加 ここまで
/* USER CODE END ET */
:
:
/* USER CODE BEGIN EFP */
//(2)追加
void Get_McuInfo(sMcuInfo_t *pMcuInfo);
/* USER CODE END EFP */
PREDMNT1_config.h 変更点(ここをクリックすると展開)
・使用する加速度センサを有効のままにし、それ以外を無効に変更
//(1)変更
#define ACCELERO_INSTANCE IIS3DWB_0//BFA001Vx_IIS3DWB_0
//(2)削除 ここから
//#define TEMPERATURE_INSTANCE_1 BFA001Vx_HTS221_0
//#define HUMIDITY_INSTANCE BFA001Vx_HTS221_0
//#define TEMPERATURE_INSTANCE_2 BFA001Vx_LPS22HB_0
//#define PRESSURE_INSTANCE BFA001Vx_LPS22HB_0
//(2)削除 ここまで
:
#define FP_PACKAGENAME "FP-IND-PREDMNT1"
//(3) 変更 ボード名の変更
#define FP_HWUSED "STEVAL-STWINBX1"
TargetFeature.h 変更点 (ここをクリックすると展開)
・ヘッダーファイルの変更
:
/* Includes ------------------------------------------------------------------*/
#include <stdlib.h>
//(1)削除 ここから
/*
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_conf.h"
#include "bfa001Vx.h"
#include "bfa001Vx_bus.h"
#include "bfa001Vx_errno.h"
#include "bfa001Vx_periph_conf.h"
#include "bfa001Vx_motion_sensors.h"
#include "bfa001Vx_motion_sensors_ex.h"
*/
//(1)削除 ここまで
#include "PREDMNT1_config.h"
#include "MotionSP_Manager.h"
#include "data_communication_srv.h"
//(2)追加 ここから
#include "main.h"
#include "stm32u5xx_hal.h"
#include "stm32u5xx_hal_conf.h"
#include "STWIN.box_motion_sensors.h"
#include "STWIN.box_motion_sensors_ex.h"
//(2)追加 ここまで
MotionSP_Config.h 変更点(ここをクリックすると展開)
・ヘッダファイルの変更
//(1)削除
#include "stm32f4xx_hal.h"
//(2)追加
#include "stm32u5xx_hal.h"
MotionSP_Manager.h 変更点(ここをクリックすると展開)
・ヘッダファイルの変更
//(1)削除
#include "bfa001Vx_motion_sensors.h"
//(2)追加
#include "STWIN.box_motion_sensors.h"
STWIN.box_errno.h 変更点(ここをクリックすると展開)
・エラー定義の追加 :
/* Common Error codes */
#define BSP_ERROR_NONE 0
#define BSP_ERROR_NO_INIT -1
#define BSP_ERROR_WRONG_PARAM -2
:
#define BSP_ERROR_MSP_FAILURE -10
#define BSP_ERROR_FEATURE_NOT_SUPPORTED -11
//(1)追加 ここから
#define BSP_NOT_IMPLEMENTED -11
#define BSP_ERROR_MALLOC_FAILURE -12
//(1)追加 ここまで
:
STWIN.box_conf.h 変更点(ここをクリックすると展開)
・使用する加速度センサのみ有効にし、それ以外は無効に設定
:
/* Define 1 to use already implemented callback; 0 to implement callback
into an application file */
//(1)変更(1から0に変更) ここから
#define USE_MOTION_SENSOR_IIS2DLPC_0 0U
#define USE_MOTION_SENSOR_IIS2MDC_0 0U
//(1)変更 ここまで
#define USE_MOTION_SENSOR_IIS3DWB_0 1U
//(2)変更(1から0に変更) ここから
#define USE_MOTION_SENSOR_ISM330DHCX_0 0U
#define USE_MOTION_SENSOR_IIS2ICLX_0 0U
#define USE_ENV_SENSOR_ILPS22QS_0 0U
#define USE_ENV_SENSOR_STTS22H_0 0U
#define BSP_NFCTAG_INSTANCE 0U
//(2)変更 ここまで
:
移植の作業としては、以上になります。
修正が完了したら、ビルド(Build)して動作を確認してみましょう。
*ビルドして動作確認
①PCとの接続
下図のように接続
・STEVAl-STWINBX1のボードとデバッガ(STLINK)を接続。
・STEVAL-STWINBX1ボードとUSB電源を接続
(USBケーブルでPCのUSB端子に接続するか、USB電源アダプタに接続)
・デバッガをPCとUSB接続

②ビルドして動作確認
-
CubeIDE上のBuildボタンをクリックしてビルド。
-
以下の画面で、パラメータを変更するか否かを選択後、FFTの解析動作が開始します。設定時間後(デフォルト:5秒)にFFTの結果がテキストで表示されます。

動作の詳細に関しては、下のユーザマニュアルを参照ください。
関連記事
- STM32CubeIDEのFWプロジェクトにソースファイルを追加(インポート)するには? - CMSIS-DSPライブラリ追加の例 - :
2. FFT(高速フーリエ変換)振動解析のSTM32マイコン用サンプルコード :
-
評価ボードSTEVAL-BFA001V2BのURL:
https://www.st.com/ja/evaluation-tools/steval-bfa001v2b.html#cad-resources ↩ -
評価ボードSTEVAL-STWINBX1のURL:
https://www.st.com/ja/evaluation-tools/steval-stwinbx1.html ↩ ↩2 -
FP_IND_PREDMNT1ソフトウェアパックのURL:
https://www.st.com/ja/embedded-software/fp-ind-predmnt1.html#overview ↩ -
FP_SNS_DATALOG2ソフトウェアパックのURL:
https://www.st.com/ja/embedded-software/fp-sns-datalog2.html ↩























