pickleでPICに書き込んでみた
pickleという、RaspiでPICの書き込みを行うプログラムがあることをご存知でしょうか?これです(↓)。
projects:pickle - wiki.kewl.org
lvpにも対応していて、5V電源があればPIC16F1788に書き込むことができます。
その存在は前から知っていたのですが、積極的に使ってみようと考えたのは、今回が初めてです。今まではPICkit3を使っていたので、使う必要がなかったのです。
Piccoloコンソール(JAVAプログラム)とPIccoloデバッガー(PICプログラム)はどちらも複製可能なので、Piccoloデバッガーの複製機能を積極的にアピールして、広めようという作戦です。¥(^_^)
で、Raspi-Piccoloの試作でPICへの書き込み機能を試してみました。
最初コマンドが良く分からなくでジタバタしましたが、ようやく使えるようになりました。
コマンドの操作はこんな感じです。
> p14 select PIC16F1788 lvp erase eeprom
> p14 select PIC16F1788 lvp program *****.hex
『Raspi-Piccolo』は通常版とZIFソケットを付けたFree版の二種類を用意しようと考えています。
構造体名が見つからない
Pic-coloは、readelfの出力を解析して変数のアドレスやサイズなどの情報を取得しています。今までは、(便宜上)全ての変数をバイト型の配列と見なして表示してきたのですが、もっと見やすい形式に整える作業に着手しました。
これまでは v_int BASE e803 だった
それを v_int int 0x3e8 1000 と表示するようにしました。
構造体も表示を改善しようとして、問題に気付きました。
typedef struct
{
I2C_TR_QUEUE_ENTRY *pTrTail; // tail of the queue
I2C_TR_QUEUE_ENTRY *pTrHead; // head of the queue
I2C_TR_QUEUE_STATUS trStatus; // status of the last transaction
uint8_t i2cDoneFlag; // flag to indicate the current
uint8_t i2cErrors; // keeps track of errors
} I2C_OBJECT ;
static I2C_OBJECT i2c_object;
変数(i2c_object )がstructure_typeだということは分かるのですが、構造体名(I2C_OBJECT)が見つかりません。orz
実は、構造体情報の出力は2種類( Abbrev Numberが5と21)あって、そのうちAbbrev Numberが5の方は構造体名が出力されないのらしいです。”I2C_OBJECT”という文字列が有るのかgrepで調べてみたですが、そもそもelfファイルに出力されていません。orz
readelfのオプション云々の問題では無さそうです。
何故、そんなことになっているのか?
?????????(<==暫く、悩んでみた)
ググッてみても、分かりません。
?????????(<==もう一度、悩んでみた)
考えてみても、分かりません。
どうすれば良いのか?
???(<==比較的簡単に結論が出た)
やれることからやる!
Abbrev Numberが21の方だけ先に処置することにしました。
Abbrev Numberが5の対策は、そのうちに見つかるかもしれません。
最後まで残ったときは、力任せにlstファイルを解析して、構造体名を取得することだってできるのですから。
Pic-colo開発の試練はまだまだ続きそうです。
Pic-coloの回路図を描いた
当初は、Raspi-Picという名称を考えていました(I2C接続を考えていた)。途中からUSBシリアル変換ICを搭載してUART接続することにしました。その結果、RaspiだけでなくPCにも接続できるようになったので、名称を”Pic-colo”に改めました。今後はブログのカテゴリを”プロジェクトPic-colo”にします。
”プロジェクトPic-colo”の最初の成果物として、Piccolo-16F1938の回路図を描きました。X-talを付けるかどうか迷ったのですが、折角USBシリアル変換ICから3.3Vが出力されるので、それを生かして付けることにしました。
ほぼ、当初構想通りの回路に仕上がりました。(パチパチパチ~)
ジャンパーの設定でPICの電源電圧を切り替えられる(5Vと3.3V)ようにしてみましたが、このまま行くかどうか思案中です。 USBシリアル変換ICの3.3V出力は50mAしか取れないので、ちょっと中途半端な気もするのです。3.3Vは外部電源から供給する方が良いかなぁ・・・
このあと、一度試作してからパターンを起こします。電源電圧を切り替えの件はそれまでお預け!
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
『なんだ、Arduino互換機じゃないか!』そう、思われた方もいらっしゃると思います
(<== Arduino UNOそっくりの回路だということは認めます)が違います!
Pic-coloは、PICの学習、プログラム開発、アプリケーションの実行環境を目指して、開発しています。そこの所、お間違えの無きようお願い申し上げます。
Bugfixは一歩ずつ
正常系の動作を少しずつ組み込んで、ようやくLチカプログラムが動くようになりました。ほっとしたのもつかの間、今度は異常系のバグが顔をだすようになりました。
バグの一つ目は、COM PORTの設定を/dev/ttyUSB0から/dev/tttiUSB1に切り替えようとしたら出来なかった、というものです。調べてみると、PORT設定機能がきちんと組み込まれていませんでした。orz
バグの二つ目は、割り込みハンドラが定義されていないプログラムをLoadしようとして、Null Stringのデコードでエラーになって機能停止した、というものです。Lチカはタイマー割り込みを使うプログラムだったので、このバグに気付きませんでした。
PORT設定の不具合は、他の方にプログラム動作を説明している最中に発覚したので参りました。(;_;)
皆、こうして強くなって行くんだ!
うん。
地雷を踏んだ
構造体へのポインタ配列の表示を確認していて、とんでもない地雷を踏んでしまいました。orz
MPLAB-Xの構造体へのポインタ配列の表示方法はこんな感じでした。
(1)展開前はtest_arrayがTest*[16]タイプでAddressが0x300という表示
(2)展開するとtest_array[0]からtest_array[15]まで縦に表示
(3)配列要素を展開するとTest構造体のメンバを表示
DWARFのデータ構造をそのまま辿っているようです。ふむ、これで良いのか・・・
ん!
異変に気付きました。test_array[0]の値が0?
test_array[0]の指し示す構造体メンバが0と7d?
そしてさらにおかしなことが・・・
test_arra[0]にtest0構造体のアドレスをセットして・・・あれ0まま!
test_arra[1]にtest1構造体のアドレスをセットしても・・・0まま!
さらにステップ実行すると・・・えっ!
ここに飛ぶ???
(暫く錯乱状態に陥ったのですが割愛します)
原因はこれ(↓)でした。
struct Test *test_array[16] @0x300;
ポインタ変数が1バイトのときと2バイトになるときの条件を調べようとして、test_arrayの配置を0x300に設定して、この異変に遭遇しました。
こんな所に変数を配置する奴(<==愚か者)がいけない
XC8って、煩く文句をつけるくせに、こういうドジは黙ってスルーするイケズです。
ぼちぼち、開発を進めて行く
長期に亘る作業計画(1か月とか3か月とか)は途中で100%頓挫することが分かっているので、最近は数日先くらいの作業予定しか立てません。(^_^;)
昨日(8/28)の作業予定は”ステータスの取得と表示”でした。
三種(RUN/BREAK/IDLE)のステータスをPIC側で設定して、ホストのメイン・ループで読み取り画面表示するというもので、大きなトラブルも無く作業を終えました。
<当面の開発予定>
2017.08.31 var other表示、ビット表示、integer表示
2017.08.30 Debugger-Dialog削除、Monitor-Dialog名称変更==>Select
Help表示方法検討
<本日> Loadとcinit、BreakとRESTART
一つ目は、”HexファイルをLoadしたら、RUNコマンドでcinitから起動できるようにする”というものです。(今はcinitを起動関数に指定する必要がある)
二つ目は、”自動BREAKが掛かったときにBREAKとRESTARTのメニュー切り替えを自動で行う”というものです。(今はBREAKメニューを操作する必要がある)
どちらも、手順ははっきりしているので、時間を掛けずに作業を終えることができると思います。(多分)
空いた時間を使って、未だ作業方針の立たない検討事項の調査を行います。
今一番の課題は・・・
『構造体へのポインター配列の表示方法の検討』です。
う~む、MPLAB-Xはどのように表示していたっけ?
先ずは、その確認から始めます。
なんとかLチカが動いた
『Lチカ・プログラムをLoadして動かす』
やろうとしたのはそれだけなのですが・・・
LoadコマンドでLチカ・プログラムをFlashメモリに書き込みました。
Runコマンドで所定のアドレス(cinit)から走り出しました。
ただ・・・
直ぐ、0番地付近に設定したBreakポイントに引っかかってしまいます。orz
Addressブレークは掛るのですが、後からLoadしたプログラムの実行をトレース出来ないので(STEP実行が効かない)、一体どこをどう走っているのか分からないまま、手探りのデバッグが始まりました。(ここからが長かった。)
何度も再起動しながら、様子を探っていきます。
Stack-OverFlow等でResetした訳では無いらしい、(PCONはクリアされたまま)
BREAK_STATUSの反復読み出しを止めると走り続ける、
モニタ・プログラムのTEST_FUNCならBREAK_STATUSの反復読み出しを止めなくても走り続ける、
・・・・・・・これって一体、何が起きてるんだ?・・・・・・・
モニタ・プログラムとLチカ・プログラムのリストを比べていて・・・ん!
COMMONのレジスタが、一部被っている?
Linkerコマンドでモニタ・プログラムとLチカ・プログラムのCOMMON領域を分けてみると・・・ビンゴ~
ようやく、Lチカが動きました。
『たかがLチカ、されどLチカ』
これは非常に大きな一歩になりました。
ーーーーーーーーーーーーーーーーーーーーー
補足(2017.08.28)
XC8コンパイラは、特別に管理された領域(Compiled Stack)に自動変数や一時変数を置きます。その際、プログラム全体のコール・グラフを作成して、変数の配置に重複が生じないようにしています。(XC8 マニュアル 5.5.2.2.1 Compiled Stack Operation参照)
Lチカ・プログラムとモニタ・プログラムは別々にコンパイルしたので、変数の配置に重複を生じていました。別にコンパイルしたプログラムをLoadして実行する、というのは今回の『肝』なので、そこは譲れません。そこでLチカ・プログラムとモニタ・プログラムでCompiled Stackが異なる領域に配置されるよう、リンカへ指示してトラブルを回避したと言う訳です。
以上、ご参考まで