B051 : WAV MODULEのSPIが動作しない件を調査しました。
冷静になってシミュレーションをしてみるとおかしな点を発見。
SPDR(SPI Data Register)に値をセットした時にSPSR(SPI Status Register)のWCOL(Write Collision Flag)がセットされています。
WCOLビットはデータ転送中にSPDRに書き込みを行った時にセットされます。
データはシフトレジスタによって1ビットずつ転送されていくのです。
言わば途中でデータが変更されたことを検出するためのビットです。
ですが、今回は最初の1バイト目の転送でこのような状態になっていました。
最初の1バイト目なので先に書き込んだデータがあるはずありません。
コリジョンが発生しているために転送が開始されず、転送しているつもりになっているコードはいつまで経ってもSPDRのSPIFビットが立つのを待っているというのが今回の現象です。
悶々としながらデータシートを見直していると気になる記述を発見。
「マスタSPIとして使用する場合、SSピンのデータディレクションはDDB2によって制御されます。」
「SPIによって入力ポートとして設定される場合、PORTB2ビットによるプルアップも有効です。」
そして、
「マスタはシフトするためのデータをSPDRに書き込むか、SSラインをプルアップしてパケットの終了を通知します。」
つまり、少なくともAVRのSPIペリフェラルはコリジョンの判定をSSラインの状態でも行っていそうだというところに行きあたりました。
確認してみるとB051はSSをスイッチの入力に割り当てています。
肝心のSDカードのCSは・・・
GPIOに接続しています。
過去に設計した基板は全てこのSSを何らかの形でCS(Chip Select)に使用していました。
ですから今回のような現象には遭遇しません。
CSはGPIOで正しく制御しているので、本来のSS側が何かまずそうです。
テストコードを確かめるとSSのプルアップは指定していません。
これを試しにプルアップして動作させてみました。
結果はビンゴ。
コリジョンが発生することもなく期待通りの動作をします。
勘違いはこうです。
誤:「SPIをマスタに設定した時にはSSは自分で制御する。だからどのポートでも良い。」
正:「SPIをマスタに設定した時にはSSは自分で制御する。だけどポートはSSを使う。」
データシートを斜め読みしていると「マスターの時はSSはユーザ設定だなぁ。」とだけ思います。
「だけ」というのが今回のポイント。
きちんと書いてあります。「SPI Pin Overrides」と。
0 件のコメント:
コメントを投稿