STM32マイコンのSDMMC機能でFileXミドルウェアを用いμSDカードにファイル書込みした時のスループットを計測してみました

# 1.はじめに
この記事はSTM32マイコンのSDMMC機能(SPIモードでは無い)を使用して、FileXミドルウェア(FatFSでは無い）でμSDカードにファイル書込みした時のスループットを計測しましたので紹介いたします。
開発ボードに搭載されているマイコンは　STM32H563ZIT6　でこのシリーズはSTM32CubeIDEから選択できるFatシステムがFatfsからFileXに変更されています。

# 2. 参考リンク
以下の記事を参考に開発しております。この場を借りてお礼申し上げます。

https://qiita.com/FAL19/items/e073ca807dfd1d5e36d5

# 3.開発環境
開発環境は以下の通り。

| No | 品名 |型式 | web |イメージ|
|:-:|:-:|:-:|:-:|:-:|
|1   |マイコンボード|NUCLEO-H563ZI|https://www.st.com/ja/evaluation-tools/nucleo-h563zi.html|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/e869e9d2-f3af-4575-ad5e-89fa556cc29b.png)|
| 2  |μSDカードスロット|AE-MICRO-SD-DIP|https://akizukidenshi.com/catalog/g/gK-05488/|![K-05488.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/dfb3d2ca-a71e-bc82-a2fb-2bb0e1210303.png)|
| 3 |μSDカード| 各種  |   ||
| 4 |開発環境| STM32CubeIDE　version:1.13.0  |   ||

マイコンボードとμSDカードスロットの接続は以下の通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/81ceb109-9132-a4b4-288a-23b8d680addd.png)

# 4.STM32CubeIDEでの設定
STM32CubeIDEでの設定は以下の設定をすれば、恐らく上手くコードが生成されると思います。

## Clock設定
メインクロックは240MHz
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/0f39f9c1-d3c9-6fdb-5bb8-9ec8bea1cb4e.png)

SDMMCクロックは48MHz
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/5e0255e9-e76a-6b21-4c8a-cc3bef37edd3.png)

## SDMMC1設定
4bitバス
clock divide = 2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/1f7345e0-e5a0-10b2-b216-03df575a9627.png)

GPIO割り当て
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/f92bbbdf-865d-b5c6-50f0-7632d4a5d2e3.png)

## FILEX設定
FileX Core = チェック入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/54c6fdcd-dd49-7abf-e97d-7c175d268a9b.png)
FX_ENABLE_EXFAT = Enabled
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/e143dfb1-c98c-47f2-e6e2-7a7a9f8c7e74.png)

# 5.ユーザコード

```C
/* USER CODE BEGIN PV */
#define FX_SD_VOLUME_NAME "STM32_SDIO_DISK"
FX_MEDIA        sdio_disk;
FX_FILE         fx_file;
ALIGN_32BYTES (uint32_t fx_sd_media_memory[FX_STM32_SD_DEFAULT_SECTOR_SIZE / sizeof(uint32_t)]);

int main(void)
{
  /* USER CODE BEGIN 1 */
 long cnt;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SDMMC1_SD_Init();
  MX_FileX_Init();
  /* USER CODE BEGIN 2 */

  UINT sd_status = FX_SUCCESS;

  int i;
  char c=21;

  char data[] = "This is FileX working on STM32";
  char data1[300];
  char data2[2048];
  
  for (i = 0;i<300;i++)
  {
	  data1[i] = c++;
	  if (c>=127){c=21;}
  }

  for (i = 0;i<2048;i++)
  {
	  data2[i] = c++;
	  if (c>=127){c=21;}
  }
  
  /********************************************/
  /* メディアオープン */
  /********************************************/
  	  sd_status =  fx_media_open(&sdio_disk,
		  FX_SD_VOLUME_NAME,
		  fx_stm32_sd_driver,
		  (VOID *)FX_NULL,
		  (VOID *) fx_sd_media_memory,
		  sizeof(fx_sd_media_memory));

  	  /* Check the media open sd_status */
  	  if (sd_status != FX_SUCCESS)
  	  {
		  Error_Handler();
  	  }

  /********************************************/
  /* メディアオープン */
  /********************************************/
	  sd_status =  fx_file_create(&sdio_disk, "STM32.TXT");

	  /* Check the create status.  */
	  if (sd_status != FX_SUCCESS)
	  {
	     /* Check for an already created status. This is expected on the
	     second pass of this loop!  */
	     if (sd_status != FX_ALREADY_CREATED)
	     {
		 /* Create error, call error handler.  */
	    	 Error_Handler();
	     }
	     else
	     {
	    	 fx_file_delete(&sdio_disk, "STM32.TXT");
	     }
	  }

  /********************************************/
  /* ファイルオープン */
  /********************************************/
	  if (fx_file_open(&sdio_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_WRITE) != FX_SUCCESS)
	  {
	     Error_Handler();
	  }

  /********************************************/
  /* ファイル書込み */
  /********************************************/
	  HAL_GPIO_WritePin(GPIOG,GPIO_PIN_12, GPIO_PIN_SET);
	  HAL_GPIO_WritePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin, GPIO_PIN_SET);
	    
	  cnt = 100000;
	  while(cnt--)
	  {
		if (fx_file_write(&fx_file, data, sizeof(data)) != FX_SUCCESS)
		{
			Error_Handler();
		}
	  }
	  HAL_GPIO_WritePin(LED1_GREEN_GPIO_Port, LED1_GREEN_Pin, GPIO_PIN_RESET);
	  HAL_GPIO_WritePin(GPIOG,GPIO_PIN_12, GPIO_PIN_RESET);

  /********************************************/
  /* ファイルクローズ */
  /********************************************/
	  if (fx_file_close(&fx_file) != FX_SUCCESS)
	  {
	     Error_Handler();
	  }

  /********************************************/
  /* メディアフラッシュ*/
  /********************************************/
	  if (fx_media_flush(&sdio_disk) != FX_SUCCESS)
	  {
	    Error_Handler();
	  }

  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

```
# 6.結果

## ①クロックスピード調査
SDMMC1モジュールに与えるクロックは48MHzとし、プリスケーラ(ClockDiv)を変化させた時の書き込み可否を調べました。

※なおこの調査はマイコンボードとSDカードをジャンパワイヤ（線長約20cm）で接続しておりますので、高速通信を行うのには元々不適な環境で行っております。本来の性能を発揮させるので有ればインピーダンスマッチングされた基板設計を行うべきでありますが、このような悪環境での参考値として捉えて下さい。

× = 書き込み不可 , △ = 不安定 , 〇 = 安定して書込み可
|No. | メーカ（型式) |容量|スピードクラス| ClockDiv = 0 | ClockDiv = 1 | ClockDiv = 2 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 
| 1 | KIOXIA EXCERIA| 32GB  |Class10|× |△ |〇|
|2 |TOSHIBA M203| 64GB  |Class10|×|×   |〇 |
| 3 |TOSHIBA M203| 16GB  |Class10|×|×   |〇|
| 4|TOSHIBA M303| 64GB  |Class10 | ×  | △ | 〇  |


## ②3MByte書込み [30Byte × 100000回]

|No. | メーカ（型式) |容量| スピードクラス | 書込み時間(秒) | 書込み速度(Byte/sec) |ClockDiv |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 1  | KIOXIA EXCERIA| 32GB  |Class10|5.69/6.31/6.32 |491k|2 |
|2 |TOSHIBA M203| 64GB  |Class10|14.87/14.95/14.96|201k|2 |
| 3 |TOSHIBA　M203| 16GB  |Class10|6.03/6.15/6.51|481k| 2  |
| 4 |TOSHIBA M303| 64GB  |Class10|13.33/13.8/14.21|217k| 2  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/d47c362b-e092-9a28-8283-8fe36c65cfc0.png)

## ③3MByte書込み [300Byte × 10000回]

|No. | メーカ |容量| スピードクラス | 書込み時間(秒) | 書込み平均(Byte/sec) |ClockDiv |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 1 | KIOXIA EXCERIA| 32GB  |Class10|6.17/6.19/6.04 |489k|2 |
| 2 |TOSHIBA M203| 64GB  |Class10|13.96/15.1/15.09   |203k|2 |
| 3 |TOSHIBA M203| 16GB  |Class10|6.01/5.99/5.99   |500k |2 |
| 4 |TOSHIBA M303| 64GB  |Class10| 15.51/11.49/11.79/11.74  |237k|2 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/4b63ba5a-ceb8-e5d7-929c-edf15c234387.png)

## ④5.12MByte書込み [512Byte × 10000回]

|No. | メーカ |容量| スピードクラス | 書込み時間(秒) | 書込み平均(Byte/sec) |ClockDiv |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 1 | KIOXIA EXCERIA| 32GB  |Class10|7.24/6.86/6.86 |733k|2 |
| 2 |TOSHIBA M203| 64GB  |Class10|15.28/15.3/16.9   |313k|2 |
| 3 |TOSHIBA M203| 16GB  |Class10|6.86/6.86/6.85   |746k |2 |
| 4 |TOSHIBA M303| 64GB  |Class10|14.2/14.19/14.05   |362k|2 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/e30bf1b5-39c2-333a-9e8d-4121a6803ab3.png)

## ⑤5.12MByte書込み [2048Byte × 2500回]

|No. | メーカ |容量| スピードクラス | 書込み時間(秒) | 書込み平均(Byte/sec) |ClockDiv |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 1 | KIOXIA EXCERIA| 32GB  |Class10|2.25/2.26/2.25 |2276k|2 |
| 2 |TOSHIBA M203| 64GB  |Class10|6.25/4.36/4.36  |1026k|2 |
| 3 |TOSHIBA M203| 16GB  |Class10|2.61/2.24/2.26  |2160k |2 |
| 4 |TOSHIBA M303| 64GB  |Class10|4.68/4.68/6.3   |980k|2 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/80488e7a-58db-9921-d302-dfbc0b5e51cc.png)


# 6.まとめ

・基板化しないと本来の性能が発揮できない
・32GBまではSDHC、32GBを超えるとSDXC規格になるためアクセス速度が倍程度違う
・セクタ単位(512Byte)未満の場合、バッファに貯めこんで一気に書込む方法と、都度書込む方法の差異は無い
・シングルセクタライト(512Byte)よりマルチセクタライト(2048Byte)の方が高速

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692988/00da98c0-031e-aa7c-c163-235a1ce103db.png)