Raspberry Pi PicoでexFATフォーマットのmicroSDXCカードにアクセスしてみました。
Raspberry Pi Pico microSD アクセステスト風景 |
FatFsモジュール
今回はFAT, FAT32のみならずexFATまで認識させたかったので、pico-examplesにあるサンプルは使用せずにFatFsモジュールを使用しました。FatFsは個人利用から商用まで利用目的を問わず、自己責任の下で自由に使用・改変・配布ができ実装例も豊富なので、自作マイコンユーザーにとっては非常にありがたいモジュールです。すでにSipeed Longan Nanoの実装においてFatFsモジュールでのexFATの動作を確認済みでしたので、そこからの修正という形をとりました。使用したバージョンはR0.14a_p2です。配線図 / ピン設定
配線図は以下の通りです。DAT0ラインの10KΩのプルアップ抵抗は必須で、これがないと正常認識しません。
配線図 |
接続対応表も記載しておきます。
注意点
Raspberry Pi PicoとmicroSDカードスロット間の配線は非常にシビアで、通常のブレッドボード用のmicroSDカードモジュールとピン配線では安定させて動作させることができませんでした(特にSDXCカード)。Raspberry Pi PicoのGPIOライブラリにはないがレジスタには存在する出力パッドのドライブ強度やSlew Rateを調整できる機能を追加実装して、これらを様々に調整したり、周波数を変更したり、ダンピング抵抗を挿入したり様々にカットアンドトライを試みましたがあまり改善効果はなく、最終的には以下の写真のような最短で4~8ピンに直挿しできる接続モジュールを作成することで安定動作を確認しました。SPIアクセスタイミングのマージン確保に関しては今後の改善の余地がありそうです。microSDカード直挿モジュール |
動作確認カード
以下、動作確認に使用したカードの情報を記載しておきます。microSDカードはFAT, microSDHCカードはFAT32, microSDXCカードはexFATフォーマットです。手持ちのmicroSDカードで認識できなかったカードはなく、エラーが生じる場合はすべて上記注意点のアクセスタイミングの問題でした。- PQI microSD 1GB
- Memorex microSD 2GB
- Transcend microSDHC 32GB (C4)
- Toshiba microSDXC 64GB (UHS-I C10)
- SanDisk microSDXC Ultra A1 64GB (UHS-I C10/U1)
- SanDisk microSDXC Ultra A1 512GB (UHS-I C10/U1)
- SanDisk microSDXC Ultra A2 1TB (UHS-I U3/V30)
pico_fatfs_testプロジェクト
https://github.com/elehobica/pico_fatfs_test に今回作成したプロジェクトを置いておきます。機能は以下の通りです。- シリアル端末で何らかのキーを入力するとスタート
- カードをマウントして認識。ファイルシステム(FAT, FAT32, exFAT)と容量を表示
- Write / Readのアクセス速度を計測して表示(各2回)
シリアル端末表示例 |
以下簡単にコードを説明します。
ffconf.h
FatFsの機能的なコンフィグレーションをffconf.hにて行います。今回はアクセス速度のベンチマークのため、比較的「広め」にコンフィグレーションしていますが、実際のプロジェクトで使用する際には例えば以下のパラメータ等について検討すればよいと思います。今回の設定と他プロジェクトの場合の検討事項
- FF_FS_READONLY 0: リードオンリーの場合は1で良い
- FF_FS_MINIMIZE 0: 使用するAPIの範囲に応じて1, 2等に設定しても良い
- FF_USE_EXPAND 1: PreAllocationを使用しないなら0で良い
- FF_USE_LFN 1: Long File Nameを使用しないなら0で良い
- FF_FS_RPATH 1: 相対パスを使用しない、または外部管理なら0で良い
- FF_FS_EXFAT 1: exFAT使わないなら0で良い
- FF_FS_NORTC 1: タイムスタンプをRTCにより正しく反映させるなら0に設定し必要な関数を実装する
tf_card.c / tf_card.h
FatFsモジュールのデバイス依存部分はtf_card.c / tf_card.hにすべて記述しています。- SPI0のピンアサインはtf_card.hで定義
- SPIのカード初期化クロックは100KHz、高速動作クロックは50MHzに設定(状況に応じて変更)
- SPIのアクセス方式は8bit, CPOL = 0, CPHA = 0, MSB First
参考までにSPIアクセスの実装部分を抜粋して記載します。1バイトの双方向アクセス、複数バイトのリードアクセス、複数バイトのライトアクセスをpico-sdkのhardware/spi.hの関数を使用して実装しました。
/* Exchange a byte */ static BYTE xchg_spi ( BYTE dat /* Data to send */ ) { uint8_t *buff = (uint8_t *) &dat; spi_write_read_blocking(spi0, buff, buff, 1); return (BYTE) *buff; } /* Receive multiple byte */ static void rcvr_spi_multi ( BYTE *buff, /* Pointer to data buffer */ UINT btr /* Number of bytes to receive (even number) */ ) { uint8_t *b = (uint8_t *) buff; spi_read_blocking(spi0, 0xff, b, btr); } ... /* Transmit multiple byte */ static void xmit_spi_multi ( const BYTE *buff, /* Pointer to data buffer */ UINT btx /* Number of bytes to transmit (even number) */ ) { const uint8_t *b = (const uint8_t *) buff; spi_write_blocking(spi0, b, btx); }
hardware_gpio_ex
今回結局使用しませんでしたが、GPIO 出力PADのドライブ強度、Slew Rate設定、および入力PADのSchmitt Trigger設定を行う関数をhardware_gpio_exディレクトリ以下に実装しました。プロジェクトのCmakeLists.txtに
add_subdirectory(hardware_gpio_ex) // ... (other settings) target_link_libraries(${bin_name} PRIVATE pico_stdlib // ... (other libraries) hardware_gpio_ex )と記載して、実際に使用するソースにて
#include "hardware/gpio_ex.h"
とすれば以下の3関数が使用できます。(使用例はtf_card.cのコメントアウトされている部分を参照)
void gpio_set_drive_strength(uint gpio, uint value); void gpio_set_schmitt(uint gpio, uint value); void gpio_set_slew_rate(uint gpio, uint value);
アクセススピード計測結果
アクセススピードとしてはかなり見劣りのする数値しか出ていません。もちろんこの程度のスピードでも問題なく使えるアプリケーションは数多くありますのでその範囲内で使用するか、高速化のチューニングをして使用するかはケースバイケースになると思います。- PQI microSD 1GB
Type is FAT16 Card size: 1.02 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 72.8148, 188153, 3175, 7028 72.7216, 188240, 3177, 7037 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 740.6934, 1591, 665, 690 740.8031, 1589, 665, 690
- Memorex microSD 2GB
Type is FAT16 Card size: 2.00 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 79.2543, 222555, 2452, 6456 78.1408, 229029, 2457, 6549 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 757.2978, 2044, 533, 675 757.4125, 2039, 533, 675
- Transcend microSDHC 32GB (C4)
Type is FAT32 Card size: 31.90 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 273.3709, 209797, 947, 1871 287.3379, 208416, 968, 1780 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 851.7343, 1192, 539, 600 851.8794, 1189, 539, 600
- Toshiba microSDXC 64GB (UHS-I C10)
Type is EXFAT Card size: 61.89 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 149.3869, 180241, 2065, 3424 155.4869, 173010, 2069, 3291 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 620.7698, 960, 621, 824 620.4617, 959, 621, 824
- SanDisk microSDXC Ultra A1 64GB (UHS-I C10/U1)
Type is EXFAT Card size: 63.83 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 464.5679, 19560, 881, 1101 471.6234, 19881, 761, 1084 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 1238.1575, 422, 394, 412 1238.1575, 422, 399, 412
- SanDisk microSDXC Ultra A1 512GB (UHS-I C10/U1)
Type is EXFAT Card size: 511.80 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 430.8212, 24998, 951, 1187 428.5318, 24974, 953, 1193 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 1195.5237, 443, 413, 427 1195.5237, 444, 415, 427
- SanDisk microSDXC Ultra A2 1TB (UHS-I U3/V30)
Type is EXFAT Card size: 1023.74 GB (GB = 1E9 bytes) FILE_SIZE_MB = 5 BUF_SIZE = 512 bytes Starting write test, please wait. write speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 426.9217, 6290, 963, 1198 427.0676, 32321, 958, 1197 Starting read test, please wait. read speed and latency speed,max,min,avg KB/Sec,usec,usec,usec 1192.9563, 445, 409, 428 1192.9563, 445, 413, 428
0 件のコメント:
コメントを投稿