概要
今回は、Microchip社の32ビットマイコン「PIC32CZ CA80」シリーズを搭載した開発ボード 「PIC32CZ CA80 Curiosity Ultra Development Board」 を使用し、SDHCモジュールを利用したuSDカードへの書込みの実装について紹介します。
記事変更履歴
| 公開/ 変更日 | 特記 |
| 25/10/19 | 初版公開 |
関連リンク
内部リンク
| 記事 | リンク | |
| 第1回 | PIC32Cシリーズ① 概要 | PIC32Cシリーズに関して – ぴくおの電子工作的な何かWP |
| 第2回 | PIC32Cシリーズ② PIC32CZ CAシリーズ | PIC32Cシリーズ② PIC32CZ CAシリーズについて – ぴくおの電子工作的な何かWP |
| 第3回 | PIC32Cシリーズ③ PIC32CZ CA80 Curiosity Ultra Development Boardについて | PIC32Cシリーズ③ PIC32CZ CA80 Curiosity Ultra Development Boardについて – ぴくおの電子工作的な何かWP |
| 第4回 | PIC32Cシリーズ④ PIC32CZ USB High-Speed モジュールの使い方 | PIC32Cシリーズ④ PIC32CZ USB High-Speed モジュールの使い方 – ぴくおの電子工作的な何かWP |
| 第5回 | PIC32Cシリーズ⑤ PIC32CZ SDHCモジュールの使い方 | PIC32Cシリーズ⑤ PIC32CZ SDHC モジュールの使い方 – ぴくおの電子工作的な何かWP |
| 項目 | リンク |
| WFI32EによるmicroSDカード書き込みスループット計測 | WFI32EによるmicroSDカード書き込みスループット計測 – ぴくおの電子工作的な何かWP |
外部リンク
| 項目 | リンク |
| PIC32CZ CA80 開発ボードサイト | PIC32CZ CA80 Curiosity Ultra Development Board | Microchip Technology |
| データーシート | PIC32CZ CA80/CA9x High Security (SG) Embedded Connectivity Family Data Sheet |
| Microchip MPLAB Harmony | Microchip MPLAB Harmony · GitHub |
| FAT filesystem using SDMMC Media | core_apps_pic32cz_ca/apps/fs/sdmmc_fat at master · Microchip-MPLAB-Harmony/core_apps_pic32cz_ca · GitHub |
開発環境
| 項目 | 値 | リンク |
| ベースボード | PIC32CZ CA80 Curiosity Ultra Development Board | PIC32CZ CA80 Curiosity Ultra Development Board | Microchip Technology |
| 統合開発環境 | MPLAB X IDE v6.25 | MPLAB® X IDE | Microchip Technology |
| コンパイラ | MPLAB XC32 v4.60 | MPLAB® XC Compilers | Microchip Technology |
| デバイスファミリーパック | 1.6.163 |
SDHCモジュールについて
概要
SD/MMCホストコントローラ(SDHC)は、組み込み型マルチメディアカード(e.MMC)仕様、SDメモリーカード仕様、およびSDIO仕様をサポートしています。SDホストコントローラ標準仕様に準拠しています。
SDHCは「SD Host Controller Simplified Specification V3.00」で定義されたレジスタセットと、e.MMCデバイスおよび拡張機能を管理するための追加レジスタを含みます。
SDHCは最大3つのクロック(バスクロック、SDHCコアクロック、および特定の機能用のスロークロック)によって動作します。SDHCを使用する前に、MCLKとGCLKの両方を設定する必要があります。
- 互換性:
– SDホストコントローラ標準仕様
– マルチメディアカード仕様
– SDメモリーカード仕様
– SDIO仕様バージョン - 1ビット/4ビットSD/SDIOデバイスのサポート
- 1ビット/4ビットe.MMC デバイスのサポート
- SD/SDIOデフォルト速度のサポート(最大SDCLK周波数= 25 MHz)
- SD/SDIO ハイスピード対応(最大SDCLK 周波数= 50 MHz)
- e.MMCデフォルト速度のサポート(最大SDCLK周波数= 52 MHz)
- e.MMCブート操作モードサポート
- ブロックサイズのサポート範囲:1~512バイト
- ストリーム、ブロック、マルチブロックデータの読み書きのサポート- 高度なDMAおよび
SDMA機能 - 内部2 x 512 (1024) バイトデュアルポートRAM
- 同期および非同期のアボートのサポート
- SDIOカード割り込みのサポート
Complete
USBモジュールブロック図
以下にPIC32CZ CAシリーズのSDHCモジュールブロック図を示します

検証内容
SDHCモジュールの基本的な挙動と実用的な性能を把握するため、今回は次の2点に焦点を当てて検証します。
1. Harmony3のサンプルプロジェクトを用いた基本的な読み込み/書き込み動作の確認
2. 各種設定条件(ブロックサイズ、バッファ長など)を変更しながらの書き込みスループット計測
開発手順
1. サンプルプロジェクトの実行
① Harmony3プロジェクト内にある「sdmmc_fat」フォルダを任意の作業用フォルダへコピーします。
この時点でプロジェクト名を変えておくと、後の識別がしやすくなります。

② PC側で、μSDカードに「FILE_TOO_LONG_NAME_EXAMPLE_123.JPG」というファイルを保存します。
保存ができたら、そのμSDカードをCuriosityボードのスロットに挿入します。

③ プロジェクトをビルド&実行します。
正しく動作していれば、SDカードのルートに「Dir1」というフォルダが自動生成され、その中に「FILE_TOO_LONG_NAME_EXAMPLE_123.JPG」がコピーされます。ここまで確認できれば成功です。。

2. プロジェクトの生成
①MPLAB X IDEを立ち上げ File >New Project.. をクリック

②Microchip Embeddedを選択し「NEXT」ボタンをクリック

③PIC32CZ8110CA80208を選択し「NEXT」ボタンをクリック

④コンパイラを選択し「NEXT」ボタンをクリック

⑤プロジェクト名、プロジェクト保存先、エンコーディングを選択し「Finish」をクリック。

3. MCC上でのモジュール追加
①プロジェクト生成が完了すると、自動でMCCが立ち上がります。

②Libraries > Harmony > System Hardware Definitions(SHD) > Main Boards > PIC32CZ-CA80-CURIOSITY-ULTRAを追加します

③追加途中でCoreを追加するか聞かれるので「Yes」をクリック

④FreeRTOS上で動作させるか聞かれるので「No」をクリック

⑥Libraries > Harmony > USB > Peripherals >SDMMC > SDMMC1を追加


⑦「SDMMC1」ブロックのダイヤマークを右クリック。出てきたメニューの 「Available Consumers」を選択し、更に出てきたメニューから「SDCMMC」を選択すると「USB High Speed Driver」ブロックが追加される。

⑧追加途中でTimeを追加するか聞かれるので「Yes」をクリック


⑨TIME のTMRダイヤマークを右クリック。出てきたメニューの 「Available Satisfiers」を選択し、更に出てきたメニューから「TCC0」を選択(今回の場合)


⑩「SDMMC」の「DRV_MEDIA」四角マークを右クリック。出てきたメニューの 「Available Consumers」を選択し、更に出てきたメニューから「File SYSTEM」を選択すると「File SYSTEM」ブロックが追加される。


⑪TCC0モジュールを呼び出します

4. 各モジュールの設定
①「PIC32CZ-CA80-CURIOSITY-ULTRA」ブロックを選択し、右のペインから「PIC32CZ-CA80-CURIOSITY-ULTRA」> 「Digital interface」でUser LED0,1とUser Switch 0,1のチェックを入れます

②「SDMMC1」を選択し、右のペインから値を設定する。

| 項目 | 設定値 | 意味 |
| Number of ADMA2 Descriptor Lines | 1 | ADMA2(Advanced DMA 2)ディスクリプタラインの数。 ADMA2とは: SDMMCコントローラが使用する高度なDMA転送方式 ディスクリプタを使って複数の非連続メモリ領域を効率的に転送可能 設定値の意味: 1: 最小限の設定。シンプルな転送に対応 値を増やす: より複雑な転送(分散/収集DMA)が可能になるが、メモリ使用量が増加 一般的な使用例: 通常のファイルシステム操作では1~2で十分 大量の小さなファイルを高速処理する場合は増やすことを検討 |
③「SDMMC」の「Instance 0」を選択し、右のペインから値を設定する。

| 項目 | 設定値 | 意味 |
| PLIB Used | SDMMC1 | 使用するペリフェラルライブラリ。SDMMC1ペリフェラルを使用。 |
| Number of Clients | 1 | このドライバを使用するクライアント(上位層)の数。通常は1つのファイルシステムが使用。 |
| Transfer Queue Size | 2 | 転送キューのサイズ。同時に保留できる転送リクエストの数。値を大きくすると応答性が向上しますが、メモリ使用量が増加。 |
| Data Transfer Bus Width | 4bit | データ転送バス幅の設定: 1-bit: 最も低速だがピン数が少ない 4-bit: 標準的な速度(現在の設定) 8-bit: 最高速(eMMCで使用可能) |
| Bus Speed | HIGH_SPEED | DEFAULT_SPEED: 標準速度(~25MHz) HIGH_SPEED: 高速モード(~50MHz、現在の設定) |
| Protocol | SD | 使用するプロトコル: SD: SDカード用プロトコル(現在の設定) eMMC: 組み込みマルチメディアカード用 |
| Card Detection Method | Use SDCD Pin | SDカードの挿入検出方法: Use SDCD Pin: 専用のカード検出ピン(SDCD)を使用(現在の設定) Polling: ポーリングで定期的にチェック(ピン節約) |
| Enable Write Protection Check? | 未チェック | 書き込み保護スイッチのチェック機能: 有効にすると、SDカードの物理的な書き込み保護スイッチの状態を確認 書き込み保護ピン(WP)の設定が必要 |
| File system for SDMMC Driver Enabled | チェック | SDMMCドライバをファイルシステム(先ほどのFileSystem設定)と連携させる設定。これが有効でないとファイルシステムからSDカードにアクセスできません。 |
④「FILE SYSTEM」を選択し、右のペインから値を設定する。

| 項目 | 設定値 | 意味 |
| Maximum Simultaneous File Access | 1 | 同時に開けるファイルの最大数。値が大きいほどメモリ使用量が増加します。 |
| Size Of Block | 512 | ファイルシステムが扱うブロック(セクタ)の基本単位(バイト)。通常は512バイト(標準的なセクタサイズ)。 |
| Size Of Media Manager Buffer | 2048 | メディアマネージャが使用するバッファサイズ(バイト)。読み書き性能に影響します。 |
| Use File System Auto Mount Feature? | チェック | ファイルシステムの自動マウント機能。チェックすると起動時に自動的にマウントします。 |
| Total Number Of Media | 1 | 接続可能なメディア(SDカード、USBメモリなど)の総数 |
| Total Number Of Volumes | 1 | マウント可能なボリューム(パーティション)の総数。 |
| Media0 | チェック | メディア0を使用するかの設定 |
| File System Types | 1 | サポートするファイルシステムタイプの数 |
| FAT File System | チェック | FATファイルシステムのサポートを有効化。 |
| FAT File System Version | v0.15 | 使用するFATファイルシステムライブラリのバージョン。 |
| Make FAT File System Read-only | 未チェック | 読み取り専用モードにする場合にチェック。書き込み機能が不要ならメモリ節約可能。 |
| OEM code page to be used | U.S. | 文字コードページの設定。日本語対応なら”Japanese”を選択することもあります。 |
| Enable exFAT File System Support | 未チェック | exFAT(拡張FAT)のサポート。大容量ファイル(4GB以上)が必要な場合に有効化。 |
| Enable Long File Name Support | チェック | 長いファイル名(LFN)のサポート。無効にすると8.3形式のみ(メモリ節約)。 |
| File name length in bytes | 255 | ファイル名の最大長(バイト)。255は標準的な最大値。 |
| Current working directory scratch buffer length in bytes | 1024 | カレントディレクトリ用の作業バッファサイズ(バイト)。 |
| Enable Cache Line | チェック | キャッシュライン機能を有効化。 |
| Aligned Buffer for Cache Management | チェック | キャッシュ管理用のアライメントされたバッファを使用。パフォーマンス向上。 |
| Aligned Buffer Length in Multiple of 512 Bytes | 512 | キャッシュバッファのサイズ。512バイトの倍数で指定。 |
⑤TCC0モジュールをクリックし、以下のパラメータ設定を行う

5. クロック設定
SDMMC1クロックを100MHz(25MHzの倍数)とSDMMC1_SLOWクロックを12MHzに設定します


6. コードの生成
「Generate」ボタンを押し、コードを生成します

7. アプリケーションコードの生成
生成されたApp.hとApp.cをそれぞれ以下のコードと差し替えます。
■App.h
#ifndef _APP_H
#define _APP_H
// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "configuration.h"
#include "system/fs/sys_fs.h"
// DOM-IGNORE-BEGIN
#ifdef __cplusplus // Provide C++ Compatibility
extern "C" {
#endif
// DOM-IGNORE-END
// *****************************************************************************
// *****************************************************************************
// Section: Type Definitions
// *****************************************************************************
// *****************************************************************************
#define APP_DATA_LEN 512
// *****************************************************************************
/* Application states
Summary:
Application states enumeration
Description:
This enumeration defines the valid application states. These states
determine the behavior of the application at various times.
*/
typedef enum
{
/* Application's state machine's initial state. */
/* The app waits for sdcard to be mounted */
APP_MOUNT_WAIT = 0,
/* Set the current drive */
// APP_SET_CURRENT_DRIVE,
/* The app opens the file to read */
APP_OPEN_FILE,
/* Create directory */
// APP_CREATE_DIRECTORY,
/* The app opens the file to write */
// APP_OPEN_SECOND_FILE,
APP_WRITE_FILE ,
/* The app reads from a file and writes to another file */
APP_READ_FILE,
/* The app closes the file*/
// APP_CLOSE_FILE,
/* The app closes the file and idles */
APP_IDLE,
/* An app error has occurred */
APP_ERROR
} APP_STATES;
// *****************************************************************************
/* Application Data
Summary:
Holds application data
Description:
This structure holds the application's data.
Remarks:
Application strings and buffers are be defined outside this structure.
*/
typedef struct
{
/* SYS_FS File handle for 1st file */
SYS_FS_HANDLE fileHandle;
/* SYS_FS File handle for 2nd file */
SYS_FS_HANDLE fileHandle1;
/* Application's current state */
APP_STATES state;
int32_t nBytesRead;
/* Flag to indicate SDCARD mount status */
volatile bool sdCardMountFlag;
} APP_DATA;
void APP_Initialize ( void );
void APP_Tasks( void );
//DOM-IGNORE-BEGIN
#ifdef __cplusplus
}
#endif
//DOM-IGNORE-END
/*******************************************************************************
End of File
*/
#endif /* _APP_H */int debounceCount;
/* アプリケーションのCDC読み取りバッファ */
uint8_t * cdcReadBuffer;
/* アプリケーションのCDC書き込みバッファ */
uint8_t * cdcWriteBuffer;
/* ホストから読み取ったバイト数 */
uint32_t numBytesRead;
} APP_DATA;
void APP_Initialize ( void );
void APP_Tasks ( void );
#endif /* _APP_H */
■App.C
#include <string.h>
#include "app.h"
#include "user.h"
#include "config/default/bsp/bsp.h"
#include "config/default/peripheral/tcc/plib_tcc0.h"
#define SDCARD_MOUNT_NAME SYS_FS_MEDIA_IDX0_MOUNT_NAME_VOLUME_IDX0
#define SDCARD_DEV_NAME SYS_FS_MEDIA_IDX0_DEVICE_NAME_VOLUME_IDX0
#define SDCARD_FILE_NAME "FILE_TOO_LONG_NAME_EXAMPLE_123.JPG"
#define SDCARD_DIR_NAME "Dir1"
#define LED_ON() BSP_LED0_On()
#define LED_OFF() BSP_LED0_Off()
#define LED_TOGGLE() BSP_LED0_Toggle()
#define BUFFER_ATTRIBUTES CACHE_ALIGN
static APP_DATA appData;
/* Application data buffer */
//static uint8_t BUFFER_ATTRIBUTES dataBuffer[APP_DATA_LEN];
// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************
static void APP_SysFSEventHandler(SYS_FS_EVENT event,void* eventData,uintptr_t context)
{
switch(event)
{
/* If the event is mount then check if SDCARD media has been mounted */
case SYS_FS_EVENT_MOUNT:
if(strcmp((const char *)eventData, SDCARD_MOUNT_NAME) == 0)
{
appData.sdCardMountFlag = true;
}
break;
/* If the event is unmount then check if SDCARD media has been unmount */
case SYS_FS_EVENT_UNMOUNT:
if(strcmp((const char *)eventData, SDCARD_MOUNT_NAME) == 0)
{
appData.sdCardMountFlag = false;
appData.state = APP_MOUNT_WAIT;
LED_OFF();
}
break;
case SYS_FS_EVENT_ERROR:
default:
break;
}
}
uint32_t time[16];
void APP_Initialize ( void )
{
/* Place the App state machine in its initial state. */
appData.state = APP_MOUNT_WAIT;
/* Register the File System Event handler */
SYS_FS_EventHandlerSet((void const*)APP_SysFSEventHandler,(uintptr_t)NULL);
time[0] = TCC0_Timer32bitCounterGet();
}
/******************************************************************************
Function:
void APP_Tasks ( void )
Remarks:
See prototype in app.h.
*/
uint32_t cnt;
void APP_Tasks(void)
{
switch (appData.state )
{
case APP_MOUNT_WAIT:
if(appData.sdCardMountFlag == true)
{
time[1] = TCC0_Timer32bitCounterGet();
appData.state = APP_OPEN_FILE;
}
break;
case APP_OPEN_FILE:
time[2] = TCC0_Timer32bitCounterGet();
appData.fileHandle = SYS_FS_FileOpen("/mnt/myDrive1/test.txt", (SYS_FS_FILE_OPEN_WRITE_PLUS));
time[3] = TCC0_Timer32bitCounterGet();
if (appData.fileHandle != SYS_FS_HANDLE_INVALID)
{
appData.state = APP_WRITE_FILE;
}
else
{
appData.state = APP_ERROR;
}
break;
case APP_WRITE_FILE:
{
char writeData[2048] ;
char cchar = 20;
for (int i=0;i<2048;i++)
{
writeData[i] = cchar++;
if (cchar>126){cchar = 20;}
}
time[4] = TCC0_Timer32bitCounterGet();
for (cnt = 0 ;cnt<9999;cnt ++)
{
SYS_FS_FileWrite(appData.fileHandle, (void*)writeData, strlen(writeData));
}
if (SYS_FS_FileWrite(appData.fileHandle, (void*)writeData, strlen(writeData)) == SYS_FS_RES_FAILURE)
{
time[5] = TCC0_Timer32bitCounterGet();
appData.state = APP_ERROR;
}
else
{
time[5] = TCC0_Timer32bitCounterGet();
SYS_FS_FileSync(appData.fileHandle); // データフラッシュ
time[6] = TCC0_Timer32bitCounterGet();
SYS_FS_FileClose(appData.fileHandle);
time[7] = TCC0_Timer32bitCounterGet();
appData.state = APP_READ_FILE;
}
break;
}
case APP_READ_FILE:
{
char readBuffer[2048] = {0};
time[8] = TCC0_Timer32bitCounterGet();
appData.fileHandle = SYS_FS_FileOpen("/mnt/myDrive1/test.txt", (SYS_FS_FILE_OPEN_READ));
if (appData.fileHandle != SYS_FS_HANDLE_INVALID)
{
time[9] = TCC0_Timer32bitCounterGet();
SYS_FS_FileRead(appData.fileHandle, (void*)readBuffer, sizeof(readBuffer)-1);
time[10] = TCC0_Timer32bitCounterGet();
SYS_FS_FileClose(appData.fileHandle);
time[11] = TCC0_Timer32bitCounterGet();
// UART出力(デバッグ確認用)
printf("Read from SD: %s\n", readBuffer);
appData.state = APP_IDLE;
}
else
{
appData.state = APP_ERROR;
}
break;
}
case APP_IDLE:
// 正常終了
printf("SDMMC rw done.\n");
break;
case APP_ERROR:
printf("SDMMC Error occurred.\n");
break;
}
}
また「initialization.c」内のSYS_Initialize関数内で、TCC0_TimerStart();関数を呼び、実行時間計測用のタイマーを開始します。
void SYS_Initialize ( void* data )
{
PORT_Initialize();
CLOCK_Initialize();
BSP_Initialize();
EVSYS_Initialize();
TCC0_TimerInitialize();
SYSTICK_TimerInitialize();
SDMMC1_Initialize();
sysObj.drvSDMMC0 = DRV_SDMMC_Initialize(DRV_SDMMC_INDEX_0,(SYS_MODULE_INIT *)&drvSDMMC0InitData);
sysObj.sysTime = SYS_TIME_Initialize(SYS_TIME_INDEX_0, (SYS_MODULE_INIT *)&sysTimeInitData);
(void) SYS_FS_Initialize( (const void *) sysFSInit );
TCC0_TimerStart();
APP_Initialize();
NVIC_Initialize();
}
結果
1. 書き込み速度の劇的な向上
小容量書き込み(条件1〜4)では、書き込み速度は1kB/s〜35kB/s程度でした。
しかし、大容量連続書き込み(条件5〜6)では、驚異的な速度向上が見られました。
- 条件5: 352kB/s (約10倍の向上)
- 条件6: 1416kB/s (約40倍の向上!)
2. バススピードの影響
- Default (25MHz)とHighSpeed (50MHz)を比較すると、小容量書き込みではほとんど差がありません
- これは、ファイル操作のオーバーヘッドが支配的であるためと考えられます
3. ボトルネックの正体
SYS_FS_FileSyncの処理時間が非常に長い(5〜7ms)ことから、書き込み後の同期処理が大きなボトルネックになっていることが分かります。
小容量書き込みの場合:
- 実際の書き込み: 0.4〜2.4ms
- 同期処理: 5〜7ms
→ 同期処理が全体の70%以上を占めています。
4. 最適な書き込み方法
実験結果から、以下のことが明らかになりました。
✅ まとめて書き込む方が圧倒的に高速
- 14Byte単体で書き込む: 1kB/s
- 512Byte×10000回: 352kB/s
- 2048Byteずつ書き込む: 1416kB/s
✅ バッファサイズを大きくする効果が大きい
- 512Byte → 2048Byteで約4倍の速度向上
| 条件 | 値 |
| SDMMC1 | 100MHz |
| SDMMC1_SLOW | 12MHz |
| カード | Toshiba/32GB/Class10 |
| 条件1 | 条件2 | 条件3 | 条件4 | 条件5 | 条件6 | |
| 書込みバイト | 14Byte | 14Byte | 512Byte | 512Byte | 512Byte×10000回 | 2048Byte×10000回 |
| Bus Speed | Default (25MHz) | HighSpeed (50MHz) | Default (25MHz) | HighSpeed (50MHz) | HighSpeed (50MHz) | HighSpeed (50MHz) |
| 関数 | 条件1(ms) | 条件2(ms) | 条件3(ms) | 条件4(ms) | 条件5(ms) | 条件6(ms) |
| SYS_FS_FileOpen (WRITE_PLUS) | 5.377 | 5.218 | 5.21 | 5.07 | 5.162 | 5.16 |
| SYS_FS_FileWrite | 0.410 | 0.384 | 2.377 | 2.102 | 14533 | 14452 |
| SYS_FS_FileSync | 7.808 | 7.683 | 7.694 | 7.466 | 5.67 | 5.63 |
| SYS_FS_FileClose | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 | 0.002 |
| SYS_FS_FileOpen (read) | 0.431 | 0.405 | 0.404 | 0406 | 0.406 | 0.404 |
| SYS_FS_FileRead | 0.487 | 0.460 | 0.463 | 0.461 | 0.876 | 2.448 |
| SYS_FS_FileClose | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 | 0.001 |
| 書込み速度 | 1kB/S | 1kB/S | 33.5kB/s | 35kB/s | 352kB/s | 1416kB/s |
結論
microSDカードへの書き込み性能を最大化するには:
- できるだけ大きなバッファサイズを使用する
- 連続して書き込む
- 同期処理の回数を減らす(まとめて書き込んでから同期)
クロック周波数を上げるよりも、書き込み方法の最適化の方がはるかに効果的であることが実証されました。
なお、今回は検証対象に含めていませんが、「microSDカード自体の性能」も転送速度に大きく影響します。
したがって、上記の結果はあくまで今回使用した環境と条件における一例であることにご注意ください。
記事についての注意点
本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。


コメント