PIC_coloにDS18B20が繋がった
PIC_coloに1wire接続の温度計DS18B20( これ↓)が繋がりました。
Arduinoのonewireライブラリ(これ↓)を持ってきて、PIC_colo用に書き換えたプログラムはすんなり動いたように見えたのですが、時折読み取った計測値がffffになっています。
実はPIC用への書き換えに不備があったのですが、最初はArduinoのライブラリを疑っていました。<(_ _)>
何が起きているか判らないままあれこれコードを弄ってみましたが、そんたことで改善する筈もありません。Raspi上で動くオシロジ(<==以前作った)で通信波形を調べると・・・
0レベルを保つ時間が他より少し長くなったところで、ROM_SEARCHに失敗していることが判りました。どうやらPICが0を出力している最中に割り込みが入って、読み取りシーケンスが崩れてしまったようです。
タイミングがクリティカルなところに割り込みの禁止と許可をいれてみると・・・
ビンゴ~
ようやく、温度計DS18B20を2回路接続することができました。
後でArduinoのonewireライブラリを見直すと割り込みの禁止と許可らしきコード
が入っていました。
お粗末
LCD_Keypad シールドが動いた
PIC_colo_miniにArduino用のLCDKeypadシールド(これです↓)を接続しました。
『LCDKeypadシールドが動いた』などと報告するのも今更な感じです。しかし、PICでAruduino用シールドが動くことが確認できたのは、管理人にとって大きな前進です。
LCDKeypadシールドは、ネット検索をかけてもLiquidCrystalライブラリを使った説明ばかりで、lcd.init()やlcd.begin()の中で何をやっているのか、全く判りません。orz
ライブラリのコードすら見つけられず困っていましたが、なんとかこれ(↓)に辿り着いて、PICで動かす目処が立ちました。
動画を撮影してみました。
デバッグ作業が勉強になった
おしなべてデバッグ作業は辛いものですが、勉強になることも多々あります。『自動機能の組み込み』では数日間のデバッグ作業を強いられましたが、不具合原因を探して調査を進めていていくつか判ったことがあります。
PIC_coloコンソールからリセット・コマンドを送ると、PIC_coloデバッガはソフトウェア・リセットを実行します。自動機能のデバッグでは何度もリセットを繰り返しました。リセットSWを使うハードウェア・リセットより色々都合が良いのですが、動作に少し動作に違いがあります。
例えばTMR1を制御するT1CONレジスタですが、ソフトウェア・リセットでは初期化されません。(↓のR/W-0/uの表示がそれを示している)
そして、これ(↓)はMCCが生成したTMR1の初期化処理です。TMR1の停止が前提のコードになっています。
(1)TMR1HとTMR1Lからtimer1ReloadValを生成している
(2)TMR1割り込みを有効にしてから割り込みハンドラを設定している
(先頭のT1COM=0は後から追加したコードです。)
これをバグと呼ぶのは酷かもしれません。しかし、PICにソフトウェア・リセット機能がある以上、それを考慮した初期化コードを生成して欲しい(T1CON=0を先頭に入れる)と思います。
もう一つ問題なのは、割り込みハンドラを登録する関数(↓)です。
割り込み許可の状態でハンドラを書き換えています。割り込みを許可する前に割り込みハンドラを登録するのが普通でしょうから、これもバグ扱いするのは酷かもしれません。
しかしPIC_coloがユーザ・プログラムを起動するときには、タイマが既に動いているかもしれないし、RUNコマンドで起動するためにはUARTの割り込みも許可されていなければなりません。パワーオン・リセットからの起動を前提とするMCCの生成する初期化コードに対して何らかの処置は必要です。
これ(↑)をPIC_coloのユーザ・プログラムの『お作法』にしようと思います。
少なくともハンドラを登録する前(もしくは登録している最中)に割り込みが発生することは防げます。
制御レジスタを0クリアする等の処置は、個別に注意を喚起することにします。
ちょっとズルをした
ようやくPIC_coloの自動起動を実現することが出来ました。
PIC_colo_Update2を使って自動起動する機能を組み込む所までは、すんなり進みました。PIC_colo_Update2が再起動する度にSTKPTRがインクリメントして行きます。
このコードをPIC_coloデバッガに移してPIC_colo_Blinkが再起動すれば完成・・・と思ったのですが、起動してくれません。PIC_coloコンソールとPIC_coloデバッガ間の通信に異常が起きています。orz
何故、PIC_colo_Update2の再起動は上手く行くのに、PIC_colo_Blinkの再起動は駄目なのでしょうか?
PIC_coloデバッガのコードにBREAK_POINTを仕込むという技を使って、再起動の処理が正しく進んでいるかどうか調べることにしました。何度もPIC_coloデバッガのコードを書き換えたので、PICkitで書き換えることにしました。
(PIC_colo_Update2を使うべきなのですが、ちょっとだけズルしました。)
どうやら、PIC_colo_Blinkのmain関数は呼び出されているようです。今度はPIC_colo_BlinkのコードにBREAK_POINTを仕込んで動作を調べて行くと・・・TIMER1を初期化した後にPIC_coloコンソールとPIC_coloデバッガ間の通信異常が起きることが判りました。
それにしても、一体何が起きているのでしょうか?
(原因が判ってしまった今は、この時点で不具合原因を推定出来なかったことを不甲斐なく思います。)
やむなく(<==PIC_colo単独のデバッグを諦めた)PICkitのデバッガを使って動作を追いかけることにしました。
PIC_coloコンソールとPIC_coloデバッガ間の通信異常を確認して、PICkitでブレークを掛けてみると割り込みハンドラの中でした。そこからステップ実行で処理を調べて行くと、PIC_colo_BlinkのCustom_ISR関数が呼び出されていないことが判りました。
あ~っ!
プログラムをロードするときに行っていたCustom_ISR関数の登録手続きのことを忘れていました。プログラムをロードせずにFlashメモリに書き込まれているプログラムを起動する場合、cinitのアドレスから実行を開始する前にCustom_ISR関数を登録する必要があったのです。
Custom_ISR関数の登録は、PIC_coloコンソール(JAVAプログラム)側の処理だったので見落としていました。
Flashメモリにauto_startフラグ、cinitアドレス、Custom_ISR関数アドレスを登録して、再起動時にそれを読み取ることにしてようやく、リセットでPIC_colo_Blinkが再起動するようになりました。
これは、PIC_coloコンソールの無い環境でPIC_coloアプリケーションを動かすための重要な一歩になります。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
それにしても、今回の不具合調査にPICkitデバッガを利用したのは、大変残念です。PIC_colo単体でもう少し不具合調査を進めることも出来たように思います。成果を急ぎすぎたのかもしれません。
私自身、PIC_coloのデバッグ・スキルをもっと高める必要がありそうです。
PIC_coloデバッガに新機能を組み込んだ
早速、PIC_colo_Update2を使って、PIC_coloデバッガに新機能を組み込みました。
新機能対応のPIC_coloコンソール(Ver.1.00h)ですが見た目は変わりありません。
新たに組み込んだのは、フラッシュメモリを14bitワード単位で読み書きする機能です。
<コマンド書式>
get_flash addr <== 0x0000..0x1ffff
set_flash addr data <== 0x0000..0x3ffff
Common_FrameのSendフィールドに上記書式のコマンドを書いて、Sendボタンをクリックすると、処理結果がReceiveフィールドに表示されます。
これを使って、PIC_coloデバッガがユーザ・プログラムを自動起動する機能を組み込みます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
この開発もPIC_colo_Update2を使います。自動起動する部分まで組み込むと自分自身を起動する度にSTKPTRが上がっていく筈。
結果が楽しみです。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
PIC_coloが少しづつ進化していきます。
PIC_colo_Update2を作った
PIC_colo_Updateは割り込み禁止の状態でPIC_coloデバッガ相当の機能を果たすユーザ・プログラムです。PIC_coloデバッガを書き換えるために開発しました。
PIC_coloデバッガの機能追加は、PIC_colo_Updateを使って次の手順で行って来ました。
(1)PIC_coloデバッガのコードを書き換える。
(2)PIC_colo_Updateを使って、新しいPIC_coloデバッガを書き込む。
(3)再起動して、新しいPIC_coloデバッガを起動する。
(4)追加機能の動作を確かめる。
(5)不具合があれば(1)に戻る。
こうして新たに組み込んだ機能がいくつかあって、現状のPIC_colo_UpdateはPIC_coloデバッガ相当の機能を果たすプログラムとは言えなくなっていました。そんな中、新たな機能を追加しようとして何度も上の手順を反復している内に、PIC_coloデバッガを壊して(不具合を抱えたプログラムを書き込んで)しまいました。orz
PIC_coloデバッガが動かないと、PIC_colo_Updateを使って書き換えることも出来ないのでお手上げです。泣く泣くPICkitを使ってPIC_coloデバッガを書き換えました。
今の方法(PIC_colo_Updateを使って何度もPIC_coloデバッガを書き換える)は、手間も掛かりリスクも高いので見直しが必要です。
やっぱり、PICkitで開発することになるのでしょうか?
う~ん(<==悩んでいる)
う~ん(<==PIC_colo単独で開発したい)
う~ん(<==まだ悩んでいる)
ん! (<==何か思い付いた?)
あらためて現状のPIC_coloデバッガ相当の機能を備えたPIC_colo_Update2を作ります。このPIC_colo_Update2が新しいPIC_coloデバッガの開発環境として打って付けだと気付きました。
(1)PIC_coloデバッガ相当の機能を備えている。
(2)簡単にリロード出来る。
(3)スナップ・ダンプをとって、動作を確認できる。
(4)PIC_colo_Update2で得た成果をPIC_coloデバッガに簡単に反映出来る。
(<==コードの差が小さい)
早速PIC_coloデバッガのコードをコピーして、PIC_colo_Update2を作りました。
改修箇所は・・・
(1)割り込み禁止にする。
(2)メイン・ループ内のポーリング処理でUART割り込みを扱う。
(3)リンカの設定をユーザ・プログラムと同じ条件にする。
これでO.K.だと思ったら、BREAK操作やSTOP操作でUARTの通信異常になりました。
二つ手順が抜けていました。
(4)break_loop内も同様にUART割り込みのポーリング処理を追加する。(5)Stop処理でPIC_coloデバッガに戻る所で割り込みを許可する。
ふ~。漸く新しいPIC_colo_Update2が動きました。
今後の機能追加は、先ずPIC_colo_Update2で行い、その成果をPIC_coloデバッガに反映します。そうすると、PIC_colo_Update2はPIC_coloデバッガ相当の機能を常に備えていることになるのです。
目出度し、目出度し。
自己完結するPIC_coloに少し自信を深めた
PIC_colo_miniのサンプル・プログラム6種が動きました。
最後のFlash_memoryでPIC_coloが動作異常を起こしました。ロードしたFlash_Memoryプログラムではなく、PIC_coloデバッガで停止したようです。Resetすると回復するので、プログラムを書き換えてしまうような不具合ではなさそうなのですが、PIC_coloデバッガ自身のデバッグは久しぶりです。
はて?何が起きているのか?PICkitを接続して調べなくても大丈夫なのか?
Resetして再起動・・・停止。Resetして再起動・・・停止。
何度も繰り返して、Common_Frameが64バイトのflash_read_buffの読み取りを掛けた所でPIC_coloが停止してしまうことが判りました。
プログラムを調べると・・・
#define SEND_BUFF_SIZE 16
#define RECEIVE_BUFF_SIZE 64
unsigned char comm_receive_buff[RECEIVE_BUFF_SIZE];
unsigned char comm_send_buff[SEND_BUFF_SIZE];
送信用バッファは16バイトしか確保していませんでした。orz
バッファサイズを超えて書き込まないように修正すると、
for( offset=0;offset<size;offset++)
{
if( offset >= SEND_BUFF_SIZE )break; <==追加した
comm_send_buff[offset] = *(pointer++);
}
PIC_coloは停止しなくなりましたが、memoryの読み取りが16バイトに制限されます。comm_send_buffを64バイトに拡張できれば良いのですが、RAMの使用量が256バイト(<==設計仕様)を超してしまいます。
さて?どうするか?
あらためてプログラムの動作を調べると・・・
(1)memory_readコマンド受信 <==comm_read_buff使用
(2)コマンド解釈
(3)コマンド実行 <==comm_send_buff使用
(4)コマンドcomplete送信 <==次のコマンド送信許可
この動作は全てのコマンドに共通(resetコマンドだけcomplete送信が無い)なので、comm_send_buffとcomm_receive_buffは共用できます。簡単に次のように書き換えて、64バイトのmemory読み取りが出来るようになりました。パチパチパチ~
#define RECEIVE_BUFF_SIZE 64
unsigned char comm_common_buff[RECEIVE_BUFF_SIZE];
#define comm_receive_buff comm_common_buff
#define comm_send_buff comm_common_buff
で、「PIC_coloが自己完結している」というのは・・・
PIC_colo_Updateプログラムを使うと0x0000~0x0fffに配置されているPIC_coloデバッガ自身の書き換えが出来ます。つまり今回の不具合対策(デバッグからPIC_coloプログラムの書き換えまで)は全てPIC_colo単体で行ったのです。
『PICkitを使わないPICプログラムの開発環境』というPIC_coloのコンセプトの実現に、少し自信が待てました。