So-net無料ブログ作成
検索選択
Bluetoothインターフェース ブログトップ

I2C通信機能の組み込みで嵌った(その7) [Bluetoothインターフェース]

(2013.07.31)

I2C通信機能のループバックテストでは最近覚えたデバッグ技(<==条件ブレーク 特にwrite specific value)のお世話になりました。

技を駆使して不具合箇所の修正とテストを繰り返していたときのことです。再起動すると”Target Halted”と表示され、デバッガが止まってしまいました。しかし、普通なら表示される筈のブレーク箇所が表示されません。

”あれ。何だこれは?”

訳が判らないままリセット・ボタンをクリックすると、メイン関数の最初の行に戻らず、先ほどと同じ所(<== PC 0xEE3)で止まってしまいます。

void main(void)
{
Initialize(); <== 普通ならリセットするとこの行で止まる

デバッガのDisassemblyも空白しか表示しませんが、PIC Memory Viewsには何やら意味ありげなコード(ループ処理)が表示されています。

”何なんだこのコードは?”

FilesペインにあったBluetooth_interface.debug.lstを眺めて、ようやく事情が判りました。
  3634  0EE1            clear_ram:
  3635  0EE1  0064     	 clrwdt
  3636  0EE2            clrloop:
  3637  0EE2  0180              clrf	indf0		;clear RAM location pointed to by FSR
  3638  0EE3  3101              addfsr	0,1      <==ここで止まっていた
  3639  0EE4  3001              movlw	1
  3640  0EE5  02FE              subwf	btemp,f
  3641  0EE6  3000              movlw	0
  3642  0EE7  3BFF              subwfb btemp+1,f
  3643  0EE8  087F              movf btemp+1,w
  3644  0EE9  047E              iorwf btemp,w
  3645  0EEA  1D03              skipz
  3646  0EEB  2EE2              goto clrloop	;have we reached the end yet?
  3647  0EEC  3400              retlw	0		;all done for this memory range, return

デバッガの初期化処理のようです。その中で以前に設定した”write specific value = 0”の条件でブレークが掛かったのです。しかし、IDEはデバッガのコードを表示しないように設定されている(らしい)ので、実行プログラムに関する情報が何も表示されなかったという訳です。

『ああ、ビックリした!』

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

I2C通信機能の組み込みで嵌った(その6) [Bluetoothインターフェース]

(2013.07.30)

SPIでループバックテストのデバッグを始めたはかりの頃のことです。

親族SNS管理人がchar型配列として定義した大きなリングバッファ領域4個(USARTの入出力用とI2CまたはSPIの入出力用)をコンパイラ&リンカは何事も無く受け入れました。しかし、IDEのDashboardに表示されたRAM消費量は殆ど増えませんでした。

”何故?”
”まぁ良いか”(<==結果オーライが親族SNS管理人の基本スタンスです)

ところがループバックテストを始めて直ぐ、watchウィンドウに表示されるリングバッファの内容がおかしいことに気付きました。

”どうして、こんな結果になるんだ?”
”プログラムのバグにしては何か変”

watchウィンドウに表示されたリングバッファのアドレスを見て・・・
SRAMの0x2170ってどこだ?”

ここで初めて、リンカがリングバッファをリニア・データ・メモリ(FSR アドレスの0x2000 から 0x29AFに割り当てられた仮想的な連続RAM領域)にアサインしたことに気付きました。そしてwatchウィンドウがリニア・データ・メモリを上手く扱えないらしいことも判ってきました。

watchウィンドウに頼れないので、リングバッファの内容を見るためには該当するFile Regsterを探さなくてはなりません。しかし、リニア・データ・メモリとFile Registerのアドレス変換はとても面倒で、数回繰り返しただけでうんざりしてしまいました。

リニア File_Register
0x2000 0x020-0x06F
0x2050 0x0A0-0x0EF
0x20A0 0x120-0x16F
0x20F0 0x1A0-0x1EF
0x2140 0x220-0x26F 
0x2190 0x2A0-0x2EF
0x21E0 0x320-0x36F
0x2230 0x3A0-0x3EF
0x2280 0x420-0x46F
0x22D0 0x4A0-0x4EF
0x2320 0x520-0x56F
0x2370 0x5A0-0x5EF
0x23C0 0x620-0x66F
0x2410 0x6A0-0x6EF
0x2460 0x720-0x76F
0x24B0 0x7A0-0x7EF

その時思いついたのが『リングバッファのサイズを128バイトから160バイトに変更する』方法です。
するとこんな感じに・・・

ring_buff1 0x20D0 0x150 send(host)
ring_buff2 0x2170 0x250 receive(host)
ring_buff3 0x2210 0x350 send(rn42)
ring_buff4 0x22B0 0x450 receive(rn42)

リングバッファの先頭が256バイト刻みになって、手作業でアドレス変換する苦労から開放されました。
パチパチパチ~

リニア・データ・メモリは80バイト単位の利用がお勧めです。

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

I2C通信機能の組み込みで嵌った(その5) [Bluetoothインターフェース]

(2013.07.29)

ようやく動きだした(と思った)ループバックテストが、数秒で止まってしまいました。タイミング依存の不具合が潜んでいるようです。

『この手のバグは苦労しがちなんだよなぁ~』

と少し身構えましたが、メイン・ループで割り込み禁止状態に陥っていることが判り、不具合原因を特定することが出来ました。問題を起こしたのは、デバッグのために設けたdi()の拡張関数でした。
void a_di(void)
{
  if( di_count == 0 )
  {
    di_state = INTCONbits.GIE;
  }
  di_count++;    <== この位置が拙い
  INTCONbits.GIE = 0;
}

void a_ei(void)
{
  if( (--di_count) == 0 )
  {
    INTCONbits.GIE = di_state;
  }
}

di_stateにGIEを記録した直後(まだdi_countは0のまま)に割り込みが入り、割り込みハンドラ内でこの関数が呼び出されるとdi_stateが0で上書きされてしまいます。
void a_di(void)
{
  if( (di_count++) == 0)
  {
    di_state = INTCONbits.GIE;
  }
  INTCONbits.GIE = 0;
}

それを上記のように書き換え、ようやく(本当にようやく)ループバックテストが動きました。
やれやれ

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

I2C通信機能の組み込みで嵌った(その4) [Bluetoothインターフェース]

(2013.07.28)

固定長データの通信であれば、I2Cのマスターとスレーブのプログラムに大きな違いは無いのですが、可変長データの場合はマスター側がスレーブの事情を考慮してデータを送受しなければなりません。スレーブ側もアクノリッジ信号を適切に返す必要があります。

これまで、スレーブの設定は”7bitアドレス、SEN = 1、AHEN = 0、DHEN = 0 ”(==>クロック・ストレッチ・イネーブル、アドレスホールドとデータホールドはディスエーブル)にしていました。しかし、これだとスレーブ側でSSPCON2.ACKDTを操作しても、希望するアクノリッジにならない(<==嘘かもしれない)のです。

そこで、設定を”7bitアドレス、SEN = 1、AHEN = 1、DHEN = 1 ”(==>クロック・ストレッチ・イネーブル、アドレスホールドとデータホールドもイネーブル)に変えることにしました。アクノリッジ・シーケンスでもSSPIFが立つので割り込み処理が煩雑になる(SSPCON3.ACKTIM、SSPSTAT.D_nA、SSPSTAT.R_nWを見て処理を決定する)のですが、この設定によってスレーブ側でもプログラムで自由にアクノリッジを制御できるようになりました。

マスターの送受信要求に対して、送信データが無い場合や受信バッファに空きが無い場合は、アドレスマッチの段階でNACKを返せる(それまでアドレスマッチでは自動的にACKが返っていた)ようになり、マスター側もデータを転送する前に中止できるので、制御アルゴリズムがすっきりしました。

また、アクノリッジ・シーケンスで二つのPICkit3にブレークを掛けられるようになり、送受信シーケンスがデバッグし易くなりました(<==これが大きかった)。

これで、ようやくループバックテストが動きだしました。

”よし、よし”

ところが数秒間動き続けたと思ったら・・・

また、止まってしまいました。これは嫌な兆候です。
orz

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

I2C通信機能の組み込みで嵌った(その3) [Bluetoothインターフェース]

(2013.07.26)

上手く動いたI2Cテスト・プログラムの処理を参考にして、ループバックテスト・プログラムを書き換えました。これで動いてくれるか・・・未だ駄目です。一旦始まったデータ通信が途中で止まってしまいます。orz

Watchウィンドウでi2c_statusを調べると、Master側とSlave側で食い違っています。しかし、『どこでどう食い違ったか』までは掴めません。そこで、i2c_statusのスナップショットをとることにしました。

160バイトリングバッファを設け、Master、Slave双方でi2c_statusの変化を記録します。ブレークしてリング・バッファの書き込みを辿ると、Master、Slaveの動作が見えてきます。

『Masterのステータスが”I2C_SEND”になり、Slaveは”I2C_READ”になる。』
『Masterのステータスが”I2C_SEND_OVER”になると、Slaveは”I2C_IDLE”に戻る。』
『Masterのステータスが”I2C_RECEIVE”になると、Slaveは”I2C_WRITE”になる。』
『Masterのステータスが”I2C_RECEIVE_OVER”になると・・・あれ?Slaveが”I2C_IDLE”にならない。』
『Masterのnack送信か、Slaveの応答か、どちらかが正しく動作していない訳だ』

こんな調子で、二つのスナップ・ショットを見比べて、MasterとSlaveの処理内容と不具合原因を推察し、少しずつデバッグを進めます。不具合箇所は着実に減っている筈なのですが、ループバックテストはなかなか動いてくれません。
そして、ついに・・・

I2C通信プログラムの変更を決意しました。
orz
(つづく)

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

I2C通信機能の組み込みで嵌った(その2) [Bluetoothインターフェース]

(2013.07.22)

最初は、”ループバックテストのプログラムをSPIからI2Cに置き換えるだけ”と気楽に考えていました。メイン・ループと割り込みハンドラの基本構造はそのまま残し、spi_send_start()をi2c_send_start()に書き換えて・・・

プログラム改修はサクサク進みます。テスト環境を準備して、reset==>run!
駄目です。Master-Slave間の送受信が両方とも動きません。

”まぁ最初はこんなもの(<==本当は動くことを期待していた) ”と心静かにデバッグを始めますが、I2Cのプログラムはなかなか動きません。(この頃は未だプルアップ抵抗を付け外ししてプログラムを書き換えていた)

I2Cと同時並行して動作するUARTやTimerの割り込みが、デバッグの邪魔になっていらいらがつのります。

”駄目だ、こりゃ~”[どんっ(衝撃)]
ついに、ギブアップ!戦略的撤退です。

ループバックテストのプログラムから一旦離れ、I2C通信だけのプログラムに書き直すことにしました。書き込み時に”Too much current”と表示される問題にも再度取り組み(この辺りはこちらをご覧下さい)デバッグ体制の建て直しを図りました。

Master-Slave間で3バイトを送受するプログラムに書き直し、ジリジリ(ステップ実行して)デバッグを進めます。

”ここでスレーブのSSPIFが立つ・・・よし、よし”
マスターにAckが返る・・・あれっ、返って来ない”
”スレーブでCKPを1にすると・・・”
”よし、よし。Ackが返ってきた”

こんな調子で、少しずつ作業を進めて行き、なんとかMaster==>Slaveの3バイト送信とMaster<==Slaveの3バイト受信が動くようになりました。
まだまだ先は長いなぁ~
orz

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

I2C通信機能の組み込みで嵌った(その1) [Bluetoothインターフェース]

(2013.07.19)

SPIを使ったループバックテストが上手くいったので、Bluetoothインターフェース基板にI2C通信機能を組み込むことにしました。

3013_0719.pngPICkit3を二個遣いする

I2C通信機能のデバッグには、PIC16F1938を2個(マスター役とスレーブ役)使います。こういう形態のデバッグは難航しがちですが、予想に違わず嵌りまくります。

先ず、スタート・シーケンスで躓きました。バス衝突割り込みフラグ (BCLIF)が立っています。

”ん?これは・・・あっプルアップ抵抗を忘れてた!”

2.2kΩのプルアップ抵抗をSCLとSDAに付けると、バス衝突は無くなってスレーブ側でアドレス・マッチの割り込みが発生しました。しかし、上手く行ったのはそこまででデータ通信は始まりません。

PICデバイスマニュアルの”マスター同期シリアルポート(MSSP)モジュール”の項を何度も読み返し、プログラムを書き換えようとして、新たな問題に遭遇しました。先ほどまで問題なく出来ていたPICへの書き込みが片方のPICkit3だけ出来なくなっています。

MPLAB Xのコンソールにはこんなエラーが表示されていました。
”Too much current has been drawn on VDD.”

”えっ、配線ミスでもやらかした?”

慌てて調べましたがブレッド・ボードの配線に問題は見つからず、あれこれ試して、SDAに付けた2.2kΩのプルアップ抵抗を外せば良い(エラーにならない)ことが判明しました。

”何故、これでToo much currentになるんだ?”

訳が判らないまま、プルアップ抵抗を付け外ししてプログラムを書き換えましたが、I2C通信のデバッグは一向に進みません。ブレッド・ボードで繰り返し部品を付け外すのも問題なので、他の方法をあらためて探し直し、ついに”プルアップ抵抗をエラーになったPICkit3のVddに接続する”という方法にたどり着きました。測ってみると、エラーになるPICkit3はVddの電圧が50mVほど高いのです。これが”Too much current”の原因でしょうか?謎は深まるばかりです。

気兼ねなくプログラムを手直し出来るようになったのですが、最近修得したデバッグ技(コンディショナル・ブレーク)を駆使しても、I2C通信のプログラムはなかなか動いてくれません。
orz

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Bluetoothインターフェースを作り始めた [Bluetoothインターフェース]

(2013.07.17)

XYステージの開発絡みで、6月中頃からこんなものを作り始めました。
rn42.pngBluetoothインターフェース基板

ステッピング・モータ・コントローラとパソコンをBluetoothで接続するインターフェース基板です。
ICが2個載っているだけの簡単な回路で、ROVING NETWORKS社のBluetooth Module(これです)とPIC16LF1938を使っています。UARTならRN-42単体で済みますが、ステッピング・モータ・コントローラはI2Cインターフェースなので、PIC16LF1938でI2C-UART間の変換を行います。

開発は以下のステップで進めました。
(1)PIC16LF1938単独のループバックテスト(I2Cの代わりにSPIを使った)
(2)RN-42とパソコンを使ったループバックテスト
(3)PIC16LF1938とRN-42とパソコンを結んだループバックテスト

ノートPCとRN-42のペアリングに苦労しました(今回初めてBluetoothを扱った)が、簡単に出来ると思っていた”PICLF1938単独のループバックテスト”にもてこずりました。そのデバッグ作業で新しい技(<==個人的に)を修得しました。

PICデバッガの”コンディショナル・ブレーク”です。

これまでPICのデバッグはライン・ブレークだけでやって来ました。それしか知らなかったと言うか、それしか無いと思い込んでいたのです。

いつもの方法(Cプログラムのソース行にブレーク・ポイントを設定する)で作業していて、アセンブラ命令にブレーク・ポイントを設定したくなって(MPLABでは簡単に出来た)、ブレーク・ポイントの設定方法を調べていて見つけました。

address_break.pngアドレス・プレーク

menu.png4種類のブレーク・タイプが選べる

debug.pngこのメニュー操作でwindowが開く

これまで使っていたLineブレーク以外にDataブレーク、Addressブレーク、Eventブレークなどが用意されていました!オンチップの機能だと思うので、全てのデバイスで利用可能かどうか判りませんが、親族SNS管理人のPIC開発力が1ランク・アップしたことは間違いありません。

難航したループバック・テストも、このデバッグ機能のお陰で、なんとか終えることができました。

nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感
Bluetoothインターフェース ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。