チカラの技術

電子工作やプログラミング

STM32の内臓フラッシュ書込み機能を使ってみる。

余りにもUSBのマスストレージ実装が遅々として進まない為、
mp3プレイヤー部分のGUIを作る作業をやって気分転換しようと思います。


○やりたい事
1.自分はmp3ファイルを歌手やジャンルごとにフォルダにまとめて、保管している。
  このフォルダを丸ごとSDカードにコピーして、自作mp3プレイヤーで読み出したい。
2.ファイル,フォルダ名を表示する。
3.曲順がバラバラにならないようファイル名でソートする。


○とっかかりの日本語を扱い始めた瞬間から、書込み速度に悩み始める。
 
 私の自作プレイヤーはファイルシステムにFATFSを利用させてもらっています。
 
 FATFSで日本語のファイル名を取り扱う為には、LFN機能を有効にします。
 しかし、このLFN機能を使用するとShiftJISとUniCode文字コード変換テーブルが必要になります。
 このテーブルのサイズは60kByteとデータ量が大きいです。
 STBEEは512kByteのROMサイズなので容量的には全く問題が無いのですが、
 ROM書込み機の速度の影響で書込み時間が20秒→1分半程になってしまいました。
 私は頻繁にプログラムを変更してデバッグをするので、書込み時間が作業効率に影響してきます。
 
○そうだ、最初から書き込もう!
 マイコンのプログラムというのは特に指定が無ければ、ROM領域の先頭から書き込まれていきます。
 そこで図のようにテーブルをROM領域の途中から書き込めば、
 テーブル領域までプログラムが書き込まれない限りテーブルは破壊されません。
 
 
イメージ 1
 こうして書き込んでおいたコードテーブルの先頭アドレスを
 コードテーブルの配列名を持ったポインタに代入すれば、
 (ポインタは配列とほぼ同等の扱いが出来る為)既存のコードをそのまま使えます。
 
例:FATFSのcc932.cの文字テーブルを指定のアドレスにあらかじめ書き込んでいる。
  また、ソースコード中の文字テーブルはコメントアウトした。
/*配列の代わりにポインタを用いる。*/
static const WCHAR *uni2sjis = (const WCHAR *)(0x08040000);
static const WCHAR *sjis2uni = (const WCHAR *)(0x0804c800);
 
/*ポインタではテーブルサイズをsizeof()で調べる事は出来ないので
 sizeof(uni2sjis)などとなっている部分を以下のマクロに置き換える。*/
#define UNI_TABLE_SIZE 29560
#define SJIS_TABLE_SIZE 29560
 
 文字テーブルは30kByteずつですが、拡張しても良いように50kByteずつ領域をとってみました。
 テーブルはROM領域の中央から書き込んでますから、プログラムコードは256kByte以上書けませんが
 実際問題プログラムコードにそんなに容量要りませんw


○どうやって書き込んだか
 トラ技2011年2月号に「DFU機能(USB書込み機能)使えばHEX書き込めます」と載っていたのですが
 私はJTAGデバッガを使っているのでDFUは消してしまいました。
 その上、JTAGデバッガを使用して指定のアドレスにデータだけ書き込む方法が見つかりませんでした(><)
 
 そこでSTM32の内臓ペリフェラルの「フラッシュ書込み機能」を使う事にしました。
  この機能なら開発環境に関係なくデータの書き込みが可能です。
 詳しくはマイコン徹底入門のフラッシュ書込み機能をご覧ください。
 (この機能は英文しか資料が無いので大変助かりました!)
 
この機能を使って、配列を指定のROMアドレスに書き込む関数を作りました。
ソースコードを晒して見ます。
※アドレスの領域チェックや,書き込むバイト数の範囲チェックは行っていませんので
  参考にする方は注意してください。
 
 
この関数はこんな感じで使います。
(LED_ONとOFFはSTBEEのLEDを操作するマクロです)
LED_ON;
stat = IntPlog_HighDensity(0x0804c800,&sjis2uni[0],sizeof(sjis2uni));
//書込みが正常に終わればLED消灯
if(stat == 0)
{
   LED_OFF;
}

○まだ・・・まだスタートライン前なんだ!
 あらかじめ書き込む事によってプログラム書込み時間の節約や、
 コンパイル容量制限のある開発環境の寿命延長が可能です。
(この場合はテーブルをROMに置かずSDカード等からバッファに読み出して書き込んでいく。
その時は関数の仮引数からconstを外す)
 文字テーブル以外にも、タイトル画像データやルックアップテーブルなど
 書き換えの頻度の低いデータに使えそうです。
 
 うまくいったと思ったら、最初に挙げた目標を何一つ達成できていない事に気づきましたorz