記事一覧

SDカードアクセス (その後)

ファイル 142-1.png

 かなり放置状態だったデータロガー 2号機計画,とりあえず単体で G を計測するやつを作ろう (これだと追加の半田付けはなんもいらんから) と思った.
 で svn に葬ったソースファイルをチェックアウトしてきて,コンパイルしてみたらコンパイルが通らねぇ(爆) 原因を追っていったらなんかいろいろとコンパイルオプションとかがおかしくね? なんでこんなとこいじったんだろう…?

 まぁめでたくコンパイルも通り,SD カードの初期化コマンドを CMD1→ACMD41 に変更したら,前回使えなかった 8MB ゴミカードも無事初期化できるようになった.

 で,前回は SD カードリードでとまっていたので,SD カードライトに挑戦.ライト速度も見るためにいろいろデバッグメッセージ出力を削ってやってみたら,

 fatfs に「ファイルシステムがねぇ」って怒られる orz

なんかデバッグメッセージを消したことにより wait が減って,動作が変になってるっぽい.まれにライトまでたどり着けたとしても,FAT エントリをめちゃくちゃに破壊してくれるんですが…(笑)

もう窓から投げ捨てていいかな?

ゴミ SD カード活用

-------- initialize --------
CMD0:1 CMD1:7 CMD1:7 CMD1:3 CMD1:3 CMD1:3 CMD1:3 CMD1:3 CMD1:3 CMD1:3 CMD1:3
-------- CSD --------
CMD9:0,FE
0000:CSD structure
0000:System specification version
002D:Data read access-time 1
0000:Data read access-time 2 in CLK cycles
0032:Max. bus clock frequency
0135:Card command classes
0009:Max. read data block length
0001:Partial blocks for read allowed
0000:Write block misalignment
0000:Read block misalignment
0000:DSR implemented
019E:Device Size
0006:Max. read current @ VDD min
0006:Max. read current @ VDD max
0006:Max. write current @ VDD min
0006:Max. write current @ VDD max
0003:Device size multiplier
0013:Erase group size
001F:Erase group size multiplier
001F:Write protect group size
0000:Write protect group enable
0000:Manufacturer default ECC
0005:Write speed factor
0009:Max. write data block length
0000:Partial blocks for write allowed
0000:Content protection application
0000:File format group
0000:Copy flag (OTP)
0000:Permanent write protection
0000:Temporary write protection
0000:File Format
0000:ECC code
0074:CRC
f_mount:0
CMD17:0,FE CMD17:0,FE CMD17:0,FE
f_open:0
CMD17:0,FE
f_read:0: read=512
f_close:0
-------- dump --------
0000:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0010:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0020:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    …
01F0:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

MassStrage.dfu で 8MB のゴミ SD カードのアクセスが失敗していたので,どこでコケているのか調べてみた.
最初は初期化シーケンスが正しくないのかと思ったが,SD の仕様書と見比べてもそんなにおかしなところはない.お次は AC タイミング的なエラーを疑ってみたが,こればっかりはオシロスコープ持ってないのでわかんね.ただほとんどのコマンド (CMD0 とか 9 とかはぜんぜん正常であることが分かってきた.てことは AC タイミング的な問題ではない?

唯一おかしいのは CMD1.こいつのレスポンスが 0x7 とか 0x3 とかしか返ってこないので,MassStrage.dfu では MSD_GoIdleState() で死んでいたようだ.でもレスポンスが 0x7 とか 0x3 とかって,ここ見る限りそもそもなんかおかしいんですが… (illegal command とかありえねー) もしかして SPI の 8bit アライメントがずれてんのか?
本来
11111111 00000001 11111111
と受け取りたいところを,2bit ずれて
11111100 00000111 111111??
と受け取ってしまってるとか.これならばレスポンスが 7→3 に変化してるのも筋が通るが,何でズレてんのかまではわかんね.ああ,こういうときオシロとかロジアナとかほしいなぁ…

で本来 CMD1 のレスポンスが 0 になるまで wait するのだが,レスポンスがおかしいまま次に進んでも CMD17 (セクタリード) とかは全然正常 (これのレスポンスとかリードデータが bit ズレ起こさないのも,上の仮定と違ってて謎).というわけでゴミ 8MB SD カードが無事活用できるようになった(?)

他の使えなかった SD カード (2GB) の解析はやってないけど,たぶんセクタサイズが 512B 以外になっててその設定 (CMD16) をやってないからじゃなかろうか?

-----
追記:
 CMD1 が Illegal Command になっていた件,どうやら SD カードの厳密な仕様的には CMD1 は受け付けなくて,CMD41 で初期化しなければならないらしい.CMD41 で初期化すると,ゴミ 8MB カードも無事使用できた.
 MMC と SD は SPI 通信を使う限り,完全互換性があるという思い込みをしてしまっていた.

FLASH 上のルーチンにリンク成功

デザインウェーブマガジン付録 ARM ボードをいぢくる続き.

FLASH に焼かれたルーチンを SRAM 実行プログラムから呼び出す方法を確立してみた.
SRAM は 20KB しかないので,printf 等の大き目のルーチンを SRAM 実行プログラムにリンクしてしまうと,当然残りの SRAM 容量が減ってしまうので開発に支障が出る.そこで FLASH 上にある printf ルーチンをリンクしてしまおうというのが今回の趣旨.

まず,FLASH 上の printf のアドレスを知るためには,
メニューの Project → Options...
Linker → List タブ → Generate linker map file
で FLASH 実行プログラムの .map ファイルを生成すればよい.たとえば printf のアドレスが 0x080063ed だったとすると,SRAM プログラムのソースで

#define printf (*( int (*)( const char *fmt, ... ))0x080063ed)

と書けば OK.

だが,これだと printf を使ってる全ファイルの修正が必要だし,いちいちプロトタイプ宣言を調べて #define を書き並べるのが面倒なので,別の方法を考えてみる.

rom_entry.s なるファイルを以下の内容

    RSEG ROM_CODE:CODE(2)
    EXPORT printf
printf = 0x080063ed
    END

で作成し SRAM プログラムのプロジェクトに追加してコンパイル・リンクすることで,FLASH 上の printf にリンクできた.この方法だと .c の修正はいらないし,.map ファイルから perl スクリプトなんかで機械的に rom_entry.s を生成できるので楽.

いろいろ FLASH 上のルーチンにリンクしたら,もともと 18KB のプログラムが 5.5KB になったよ(笑)

SD カード FAT アクセス成功

ファイル 106-1.png

デザインウェーブマガジン付録 ARM ボードをいぢくる続き.

昨日と今日にかけて,フリーの FAT ファイルシステムドライバであるFatFsを組み込んで,SD カードのファイルを読み出せるようにしてみた.

具体的には,ff.c を組み込んで,diskio.c をインプリしていくのだが,disk_read/write() はほとんど SD カードセクタリード・ライトそのまんまだが,disk_ioctl() は何書いていいのか分からん… 幸いここにサンプルがあった.

デバッグ用にシリアル出力を大量にしているとなぜかリードデータが化ける問題があってちょっとハマッたが,最終的に無事ファイルリード完了ヽ(´ー`)ノ

あと,putchar() 関数を定義して,こいつでシリアル出力するようにしておくと,printf() で普通にシリアルにメッセージが出せるので便利ヽ(´ー`)ノ

以下,ToDo リスト
・FLASH のルーチンを SRAM プログラムからコールする仕組みを確立
・SRAM ルーチンを割込みハンドラに設定
・割り込みを使用したシリアル入出力
・ここら辺が FIX したら FLASH に焼いて,「SD カード上のファームを SRAM にロード」を運用開始

SD カードセクタダンプ成功(?)

ファイル 105-1.png

データロガー 2号機計画を ゆっくり と進行中.

今回は,MassStrage を参考に,SD カードの 1セクタをリードしてシリアル (USB を介した仮想 com ポート) 出力にダンプさせてみた.まぁ MassStrage の msd.c あたりをそのまま組み込んだだけだが.コンパイル通すのに多少苦労しつつ,とりあえずダンプできるまでこぎつけた.

が,シリアル出力が明らかにおかしい.シリアル出力はカエルがぴょんのやつを参考にしていて,USB の送信データバッファ(?) に送信したい文字列を直接コピーしているのだが,おそらく前のやつが送信されきらないうちに次の文字列を上書きしているのだろう.

普通は,アプリ側でリングバッファを用意して,送信したいデータはリングバッファに書く→USB 送信データバッファに空きができたら割込み発生→割込みルーチンで,リングバッファから送信データバッファにコピー,なんて流れになると思うのだが…
もうちっと Cortex の割り込みを勉強せにゃならんね.とにかくシリアル出力をまともにしないと,まともなデバッグができねぇ.

とりあえず,断片的に見えているダンプデータを見る限り,SD カードセクタリードはできているようだ.

----
6/16追記:
とりあえず割り込みを使用しないでお茶を濁しモード.送信データをバッファにカキコ前に

while( GetEPTxStatus( ENDP1 ) == EP_TX_VALID );

で前回のデータが送信されきるまで待つことで,シリアル出力は正常になったヽ(´ー`)ノ

シリアル経由 FW ローダ完成

ファイル 104-1.jpg

前回の記事どおり,SD カードの FW を SRAM にロードする仕組みを作っていくが,その前に,シリアル経由で FW を SRAM にロードする仕組みを作る.いくら既存のライブラリが充実しているからって,一発で SD カードアクセスプログラムが動くわけが無いのでw

というわけで,
1. 起動されたらデータを 0x4800 バイト分,シリアル (USB経由) から読み込んで 0x20000000~ へ書き込む
2. 0x20000004 に格納されているエントリポイントにジャンプ
という恐ろしく単純なプログラムを FLASH に焼きこんだ.これすらも,デザインウェーブマガジンに載っていたカエルがぴょんプログラムをちょこっと書き換えただけ.

ちなみに,マガジン付属 CD に入っていたサンプルプログラムの多くは,IAR Embedded Workbench でコンパイルしようとすると「__program_start」シンボルが無い,などと怒られてしまうが,その対処法はここに載っているようだ.

そしてマガジンに載っていた LED を点滅させるプログラムを SRAM 実行用に書き換え→.s19 を 0x20000000 からのバイナリイメージに変換するプログラムを作って変換→TeraTerm の send file で基盤に送信,で無事 LED が点滅したヽ(´ー`)ノ

これで内蔵 FLASH を書き換えることなく開発・デバッグができる.しかし,早いことベース基盤を作らないと,リセットボタンすらないのでやりにくぅ.

ちなみにメモリマップは前回からさらに変わっている↓

20000000ベクタテーブル
200000ECSRAM プログラム用 .text
・・・SRAM プログラム用 .data .bss 等
・・・空き
・・・スタック
(SRAM後端)FLASH プログラム用 .data .bss 等
20005000

SRAM 実行用プログラムのコード・ベクタテーブルを SRAM の前端で固定したかったので,FLASH 実行用 SRAM 領域を SRAM の最後尾にやって,そこからスタック領域とした.

データロガー2号計画発動

デザインウェーブの Cortex-M (AAM ARM) 基盤を使ったデータロガー 2号機作成をぼちぼち開始.

とりあえずの目標としては,SD カード上のファームウェアを SRAM 上にロードする仕組みを作る.で開発途上は SD カードにファームを書き込むことで Cortex 内部 FLASH の書き込み回数を減らす.これだとコード + データが 20KB 以内しか作れないが,デバッグの終わったルーチンをまとめて内部 FLASH に追い出して,SRAM 上のプログラムから FLASH 上のルーチンを呼び出す.なんてことを H8 の時はしてた.(H8 は SD カードアクセスはできなかったので,シリアル経由の .mot ロードだったが)

で,SD カードアクセスのライブラリは MassStrage デモのライブラリがそのまま使えそうだ.FAT アクセスライブラリも使われてるかと思ったら,FAT の管理をやってるのは Windows 側なのね.なのでフリーの FAT ライブラリを探してみたら,ここのが使えそうだ.

で,いろいろ make してると,メモリマップがちょとヘンなことが発覚.常識的には SP の初期値は RAM 領域最後尾の 0x20005000 だと思うのだが,標準だと 0x20000000 + プログラムで使う分 + 0x200 くらい.RAM あまりまくってるのにもったいない.

これは gcc でいうところのリンカスクリプトがおかしいのだろうと思っていろいろいじってみた.俺がインストしたのは「IAR Embedded Workbench」なので,リンカスクリプトに相当するのは「STM32F10x_FLASH.icf」になる.で以下のように書き換えた.

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08003000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x080030ec;
define symbol __ICFEDIT_region_ROM_end__   = 0x0801FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x20004FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x0;
define symbol __ICFEDIT_size_heap__   = 0x200;
/**** End of ICF editor section. ###ICF###*/


define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
place at address mem:( __ICFEDIT_region_RAM_end__ + 1 ) { block CSTACK };

define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

define block RAM_Block with fixed order { rw, block HEAP };

place in ROM_region   { readonly };
place in RAM_region   { block RAM_Block };

要は,もともとの .icf ではデータ・ヒープ・スタックを連続領域にとっていたのだが,STACK を独立させて 0x20005000 から サイズ 0 で(笑) 固定的に取っただけ.
てか,gcc のリンカスクリプトはドキュメントが充実してるし高機能だし楽なんだけど,ツール独自のリンカスクリプトはわけが分からん…

ARM 基盤に SD カードスロット装着

ファイル 100-1.jpg

デザインウェーブマガジン 5月号の ARM 基盤用追加部品が届いたので,ハンダ付けしてみた.追加部品は,マガジンに載っていた販売サービスではなく,ツクモロボット王国で買った.こっちのほうが送料が安かったので.

で,チャッチャとハンダ付けして,ハンダ付けがうまく行ってるかどうか確認するために MassStorage.dfu を焼きこもうとして,DfuSe Demo に MassStorage.dfu をロードしたら,

「This file doesn't have a correct format...」

工エェェ(;゚Д゚)ェェエ工!?


まさか編集者も収録ファイル間違えるなんてことはしないだろうし,そんなことしたら web 上で祭りになってるはずだし,メッセージをググって見てもそれらしい人は皆無.何で俺だけ…(゜ーÅ)ほろり

で,ふと思いついて,CD-ROM 上のイメージファイルを HDD にコピーして,それをロードしてみたら OK.なんと,CD-ROM 上のファイルを直接焼きこもうとすると NG だった.こんなこともあるんやねぇ…

てなわけで手持ちの SD カードを試してみたら,3枚中 1枚しか正常アクセスできなかった.認識率ひくぅ!!Σ( ̄□ ̄; せっかく 8MB のゴミ SD カードを活用できるかと思ったが,こいつは使えなかった…

まぁ,一通り動くことは確認できたので,お次は SD カード上に置いた FW を SRAM にロードする仕組みを作らないとな.何回も chip 上のフラッシュを書き換えるわけには行かないので.

今月の DesignWave マガジン

今月の DesignWave マガジンの付録,ARM が乗ったマイコンボードで,加速度センサがついていて,USB ケーブルで Flush 書き込みができそう(?) で,SD カードスロットを別途つければ,SD カードアクセスもできそうで,んーーーーこれは欲しい!

でもこれ知ったの今日だし,売り切れの中いろんな書店を探すのも面倒くさいので,HUNDAI W240D とともに Amazon でポチットな,してしまった.久々の衝動買いw

しかしこの ARM ボード,今使ってる H8 マイコンよりも高機能なので,いろいろできそうだな.っていっても,ネタ的にはデータロガー 2号機くらいしかないのだがw SD カードスロット足せば,これだけで G センサーのデータロガーができるし,A/D コンバータが 16ch もあるので,水温とか油温度とかアクセル開度とかいろいろロギングできたらいいな.

ページ移動

  • 前のページ
  • 次のページ