SDカードの読み出し速度向上とオーバークロック
こんにちは。
共立2000円液晶で動画表示を目指しています。
動画再生の仕組みは至って簡単で、画像をフレームレートの数だけ連続で描画するだけです。
画像表示は前回成功したので、残るは以下の作業だけです。
①PC上でmp4などの動画からマイコンで扱える画像データへ変換
②STM32F4の読み出しバッファに画像データを供給する。
①については自作のソフトを作りました。改良して公開できればと思っています。
今回は②について話します。
○転送速度の見積もり
バッファに供給する1秒当たりのデータ量を決定します。
①いきなり妥協
液晶は24bitカラーで表示できるのですが、
正直肉眼でじっくり見ても16bitカラーとの差が判別できなかったので動画は16bitカラーとします。
②2000円液晶、恐ろしい子!
実際に見積もって見ます。
480×272×2 (16bitカラー) × フレームレート = 1秒辺りの転送量
ヤバイ。
STM32F4が読み出せるSDカードの理論上の最大転送量はデータバス×クロックなので
0.5 (4bit) × 24MHz = 12MByte/secです。
つまり50フレーム以上は理論値を超えているのです。
③もはや運
次にSDカードをかき集めて実際の読み出し速度を調べてみました。
この中で最も転送速度が速かったのがPQIの8GBカードで(下段、左から2番目)
9.4MByte/secでした。(マイコン側のバッファサイズは100kbyte)
マイコンでの読み出し速度はPCと違い、価格やスペックに全く比例しない所が厄介です。
取り出して使ってみるまで分からないのでSDカードというよりデュエルカードみたいです。
③フレームレートの決定
決定というより、むしろ30fpsしか選択肢はありません。
しかし、ここでコントローラ無し液晶の問題が立ちはだかります。
フレームレート=リフレッシュレートが低いと画面にチラつきが生じてしまうのです。
リフレッシュレートとチラつきの認識度合い
30fps:ハッキリ分かる。
40fps:かすかに分かる
50fps:全く分からない
葛藤しましたが、やはり綺麗に動画を再生したかったので50fpsを目標としました。
限界を超えねばなぁJOJO・・・
○SDカードのオーバークロック
実はとんすけさん,ねむいさんは転送速度の限界を既に破っています。
何をしているのかというとSTM32F4を下記のように設定して
SDカードへのクロックを24MHz→48MHzと倍増させているのです。
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Enable;
これはSTM32F4のSDカード制御としてはオーバークロックでSDカードが壊れる可能性すらありますが
規格の中に納まっていたのでは達成できない転送量はやはり魅力的です。
という事で先ほどのSDカードを全てオーバークロックしてみました。
しかし読み出しができたのはなんとそのうち一つだけでした。
しかも読み出しが凄く不安定で開始後数秒で読み出しが出来なくなってしまいます。
○最強のSDカードとは
ここで数日間行き詰ってしまいました。
オーバークロック無しで複数のSDカードを使う事も考えましたがSPIによる
SDカードの転送量は3Mbyte/sec程度なのでそれでも足りません。
バッファを分ける事によって転送速度が逆に下がる可能性もあります。
煮詰まってたところでとんすけさんがカードを紹介してくれました。
『私が出会った中で最強のカードはKINGMAX製キティーちゃんの4GB CLASS4のものです。
50MHzで18MB/sでました^^』
キティーちゃん!? と色んな意味で驚きを隠せませんでしたが、
本当に困っていたので早速amazonで購入しました。
心なしか輝いて見えます。
ドキドキしながら転送量を調べたところ自分の環境では14.8MByte/secでした。
おお、50fpsの目標クリアです!
しかし、これも数秒後に読み出しが出来なくなってしまいました。
・・・困った。
○オーバークロック対策
読み出しの不安定さを解決すべく調べて対策をしました。
結果、下記の対策により安定して読み出せるようになりました。
1.インダクタの除外
SDカードの回路は下記のようになっています。
このうち電源ラインのインダクタはSDカードから発生する(マイコンボードへの)電源リプルを
低減させるフィルタの役割をしています。
しかし、オーバークロックによって消費電流が増した事で、インダクタが電流供給の妨げになり
十分な供給がされなくなっていたという事が分かりました。
そこでインダクタを除外して直接マイコンボードの電源をSDカードの電源へ接続しました。
電源リプルが100mV程度になりましたが、マイコンの動作に影響はありませんでした。
しかしオーディオを扱う際は注意したほうが良さそうですね。
2.配線は最短に
バスクロックが上がった事で信号線長による信号の反射が大きくなり、耐ノイズ性が低下しました。
DISCOVERYボードから5cm程度の配線でも読み出せなくなります。
フェライトコアを使っても効果はありませんでした。
そこでソケットピンに直接接続して配線長を最短にしました。
Vddピン以外はソケットに直接差し込んでます。
○DMAの競合問題
読み出しは安定してできるようになったものの、
フレームレートを上げると再生中に画面上に液晶欠けのような白い点がポツポツと出るようになりました。
これはDMAの転送が競合している事によって起こる現象です。
LCD表示用の内臓SRAM→GPIOへのDMA転送と、
SDカード読み出し用のSDIO→内臓メモリへのDMA転送は共にDMA2のみアクセス可能で
DMAを使うと競合は避けられません。
そこでSDカードの読み出しをソフトウェアポーリングに変更しました。
SDIOのFIFOにデータが溜まるとフラグが立つのでそれを待ってCPUで内蔵メモリへデータを転送します。
効率の良いマルチブロック転送のポーリングプログラムをとんすけさんに教えていただきました。
ポーリング待ち部分のプログラムです。
do {
if (STA_RXFIFOHF_BB_FLAG) {
pbuff[0] = SDIO->FIFO;
pbuff[1] = SDIO->FIFO;
pbuff[2] = SDIO->FIFO;
pbuff[3] = SDIO->FIFO;
pbuff[4] = SDIO->FIFO;
pbuff[5] = SDIO->FIFO;
pbuff[6] = SDIO->FIFO;
pbuff[7] = SDIO->FIFO;
pbuff += 8;
}
} while (!((sta = SDIO->STA) & SDIO_BLOCK_READ_STATUS_MASK) && timeout--);
DMAと比較しても速度に遜色ありませんでした。
○もう一声!!
これで50fpsで再生する為の読み出し環境がやっと整いました。
しかし・・・50fps・・・なんだか凄く中途半端です・・・
秋月300円液晶は60fpsだったというのもあるし、
60fpsの動画は再生できないという制約も気になります。
せっかくなのでさらに転送速度を上げる為にチューンする事にしました。
調べた結果、ボトルネックはやはりSTM32F4側のバッファサイズでした。
バッファサイズが小さいとマルチブロック転送で一度に読み込めるブロック数が少なくなり
転送速度が低下するのです。(詳しくはこちら)
前回、秋月300円液晶の時も最後はバッファサイズを拡大して転送速度不足を解決しました・・・
バッファサイズを100kByteから120kByteまで拡大しました。
これはSTM32F4の内臓SRAM(DMAでアクセスできないCCM領域を除く)のほとんど全てになります。
マイコンのリソースをほぼ全てSDカード読み出しに注ぎ込んだ結果、
転送量は15.8Mbyte/secまで向上しました!
これでやっと60fpsで動画を再生する準備ができました!
○謝辞
今回、様々な過程で煮詰まった際に貴重なアドバイスをくれた
とんすけさん、J.SHIMADAさん、本当にありがとうございました!
○参考サイト
とんすけさん:SDカードのベンチ比較 マイコン工作で速いカードはどれ?
ねむいさん :STM32F4シリーズを使ってみる3 -FatFsと下部レイヤ(SDIO・MMC)ドライバたちの実装-
共立2000円液晶で動画表示を目指しています。
動画再生の仕組みは至って簡単で、画像をフレームレートの数だけ連続で描画するだけです。
画像表示は前回成功したので、残るは以下の作業だけです。
①PC上でmp4などの動画からマイコンで扱える画像データへ変換
②STM32F4の読み出しバッファに画像データを供給する。
①については自作のソフトを作りました。改良して公開できればと思っています。
今回は②について話します。
○転送速度の見積もり
バッファに供給する1秒当たりのデータ量を決定します。
①いきなり妥協
液晶は24bitカラーで表示できるのですが、
正直肉眼でじっくり見ても16bitカラーとの差が判別できなかったので動画は16bitカラーとします。
②2000円液晶、恐ろしい子!
実際に見積もって見ます。
480×272×2 (16bitカラー) × フレームレート = 1秒辺りの転送量
ヤバイ。
STM32F4が読み出せるSDカードの理論上の最大転送量はデータバス×クロックなので
0.5 (4bit) × 24MHz = 12MByte/secです。
つまり50フレーム以上は理論値を超えているのです。
③もはや運
次にSDカードをかき集めて実際の読み出し速度を調べてみました。
9.4MByte/secでした。(マイコン側のバッファサイズは100kbyte)
マイコンでの読み出し速度はPCと違い、価格やスペックに全く比例しない所が厄介です。
取り出して使ってみるまで分からないのでSDカードというよりデュエルカードみたいです。
③フレームレートの決定
決定というより、むしろ30fpsしか選択肢はありません。
しかし、ここでコントローラ無し液晶の問題が立ちはだかります。
フレームレート=リフレッシュレートが低いと画面にチラつきが生じてしまうのです。
リフレッシュレートとチラつきの認識度合い
30fps:ハッキリ分かる。
40fps:かすかに分かる
50fps:全く分からない
葛藤しましたが、やはり綺麗に動画を再生したかったので50fpsを目標としました。
限界を超えねばなぁJOJO・・・
○SDカードのオーバークロック
実はとんすけさん,ねむいさんは転送速度の限界を既に破っています。
何をしているのかというとSTM32F4を下記のように設定して
SDカードへのクロックを24MHz→48MHzと倍増させているのです。
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Enable;
これはSTM32F4のSDカード制御としてはオーバークロックでSDカードが壊れる可能性すらありますが
規格の中に納まっていたのでは達成できない転送量はやはり魅力的です。
という事で先ほどのSDカードを全てオーバークロックしてみました。
しかし読み出しができたのはなんとそのうち一つだけでした。
シリコンパワー speed10 8GB
読み出し速度は12.8MByte/secで残念ながら目標に達成していません。しかも読み出しが凄く不安定で開始後数秒で読み出しが出来なくなってしまいます。
○最強のSDカードとは
ここで数日間行き詰ってしまいました。
オーバークロック無しで複数のSDカードを使う事も考えましたがSPIによる
SDカードの転送量は3Mbyte/sec程度なのでそれでも足りません。
バッファを分ける事によって転送速度が逆に下がる可能性もあります。
煮詰まってたところでとんすけさんがカードを紹介してくれました。
『私が出会った中で最強のカードはKINGMAX製キティーちゃんの4GB CLASS4のものです。
50MHzで18MB/sでました^^』
キティーちゃん!? と色んな意味で驚きを隠せませんでしたが、
本当に困っていたので早速amazonで購入しました。
心なしか輝いて見えます。
おお、50fpsの目標クリアです!
しかし、これも数秒後に読み出しが出来なくなってしまいました。
・・・困った。
○オーバークロック対策
読み出しの不安定さを解決すべく調べて対策をしました。
結果、下記の対策により安定して読み出せるようになりました。
1.インダクタの除外
SDカードの回路は下記のようになっています。
このうち電源ラインのインダクタはSDカードから発生する(マイコンボードへの)電源リプルを
低減させるフィルタの役割をしています。
しかし、オーバークロックによって消費電流が増した事で、インダクタが電流供給の妨げになり
十分な供給がされなくなっていたという事が分かりました。
そこでインダクタを除外して直接マイコンボードの電源をSDカードの電源へ接続しました。
電源リプルが100mV程度になりましたが、マイコンの動作に影響はありませんでした。
しかしオーディオを扱う際は注意したほうが良さそうですね。
バスクロックが上がった事で信号線長による信号の反射が大きくなり、耐ノイズ性が低下しました。
DISCOVERYボードから5cm程度の配線でも読み出せなくなります。
フェライトコアを使っても効果はありませんでした。
そこでソケットピンに直接接続して配線長を最短にしました。
Vddピン以外はソケットに直接差し込んでます。
○DMAの競合問題
読み出しは安定してできるようになったものの、
フレームレートを上げると再生中に画面上に液晶欠けのような白い点がポツポツと出るようになりました。
これはDMAの転送が競合している事によって起こる現象です。
LCD表示用の内臓SRAM→GPIOへのDMA転送と、
SDカード読み出し用のSDIO→内臓メモリへのDMA転送は共にDMA2のみアクセス可能で
DMAを使うと競合は避けられません。
そこでSDカードの読み出しをソフトウェアポーリングに変更しました。
SDIOのFIFOにデータが溜まるとフラグが立つのでそれを待ってCPUで内蔵メモリへデータを転送します。
効率の良いマルチブロック転送のポーリングプログラムをとんすけさんに教えていただきました。
ポーリング待ち部分のプログラムです。
do {
if (STA_RXFIFOHF_BB_FLAG) {
pbuff[0] = SDIO->FIFO;
pbuff[1] = SDIO->FIFO;
pbuff[2] = SDIO->FIFO;
pbuff[3] = SDIO->FIFO;
pbuff[4] = SDIO->FIFO;
pbuff[5] = SDIO->FIFO;
pbuff[6] = SDIO->FIFO;
pbuff[7] = SDIO->FIFO;
pbuff += 8;
}
} while (!((sta = SDIO->STA) & SDIO_BLOCK_READ_STATUS_MASK) && timeout--);
DMAと比較しても速度に遜色ありませんでした。
○もう一声!!
これで50fpsで再生する為の読み出し環境がやっと整いました。
しかし・・・50fps・・・なんだか凄く中途半端です・・・
秋月300円液晶は60fpsだったというのもあるし、
60fpsの動画は再生できないという制約も気になります。
せっかくなのでさらに転送速度を上げる為にチューンする事にしました。
調べた結果、ボトルネックはやはりSTM32F4側のバッファサイズでした。
バッファサイズが小さいとマルチブロック転送で一度に読み込めるブロック数が少なくなり
転送速度が低下するのです。(詳しくはこちら)
前回、秋月300円液晶の時も最後はバッファサイズを拡大して転送速度不足を解決しました・・・
バッファサイズを100kByteから120kByteまで拡大しました。
これはSTM32F4の内臓SRAM(DMAでアクセスできないCCM領域を除く)のほとんど全てになります。
マイコンのリソースをほぼ全てSDカード読み出しに注ぎ込んだ結果、
転送量は15.8Mbyte/secまで向上しました!
これでやっと60fpsで動画を再生する準備ができました!
○謝辞
今回、様々な過程で煮詰まった際に貴重なアドバイスをくれた
とんすけさん、J.SHIMADAさん、本当にありがとうございました!
○参考サイト
とんすけさん:SDカードのベンチ比較 マイコン工作で速いカードはどれ?
ねむいさん :STM32F4シリーズを使ってみる3 -FatFsと下部レイヤ(SDIO・MMC)ドライバたちの実装-