function_listにcinitを追加した
mapファイルを解析してcinitのアドレスを取得するのは簡単でした。それをfunction_listの末尾に表示させるところで、手間取ってしまいました。
function_listはelf(dwarf)ファイルの解析結果をリスト形式で記録しています。そこにcinitのアドレスを追加すれば良いと考えたのですが・・・
デバッガで確認するとcinitの情報はfunction_listに追加されているのですが、画面には表示されません。orz
調べてみると、elfファイルを解析した直後に関数リストをファイルに書き出していて、それを読み出して表示していました。cinitの情報を追加したのがファイルに書き出した後だったので、cinitが表示されなかったのです。
やれやれ
(ボチボチ、ボチボチ。開発を進めて行きます)
次はBreak StatusとBreak Conditionを扱います。
cinitのことを忘れていた
PICのProgram Memoryを眺めていて、リセットからMain関数が呼び出される前に、何か処理していることに気が付きました。
リスト・ファイルを調べて見ると・・・Cプログラムの初期化処理(cinit)です!
ユーザ・プログラムの起動は、単純にmain関数を呼び出せば良いと考えていました。しかし、それでは初期化変数に値が設定されません。ユーザ・プログラムの起動は、main関数ではなくcinitを呼び出さなくてはならなかったのです。orz
関数リストにはcinit(<==Cプログラムではない)は含まれていません。mapファイルに記されているのでcinitの先頭アドレスを得ることは出来そうです。
こりゃ、まだまだ抜けが有りそうだ。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
xc32の方はどうなっているのか気になりますが、先ずはxc8を仕上げることに専念します。
PIC側の機能はほぼ揃った
Break ConditionがTHROUGHならBreak StatusはTHROUGH(またはNULL)、Break ConditionがBREAKならBreak StatusをBREAKにしてBreak_Loopを呼び出す。RESTARTコマンドでBreak_Loopを抜けて、元の関数に戻る。これがBreakの動作仕様です。
Break ConditionにTHROUGHやBREAKを設定するのはMEMORY_WRITEコマンドで、Break StatusがNULLなのかTHROUGHなのかBREAKなのか調べるのはMEMORY_READコマンドで行います。ホスト側の操作をPICkit3で代行して、仕様の確認を済ませました。
Break_Loopの実行制御はBREAKコマンドとRESTARTコマンドでテスト済みです。
どうやらPIC側の機能はほぼ揃いました。
残っているのは、PICから読み出したVarやRegの値を編集して、PICに書き戻す処理です。PIC側はMEMORY_READとMEMORY_WRITEの動作なので、ホスト側で行うデータ操作が課題になります。
また、ゴリゴリ、ゴリゴリ、プログラムを書いていきます。
PICkit3の夏バテ対策を見つけた
現在の気温は27度。久しぶりに涼しい朝を迎えています。お陰様でPICkit3も好調です。
気温が30度を越すとPICkit3の調子がおかしくなる(<==夏バテと呼んでる)のですが、最近頻発するのが”A tool request has been waiting for・・・”というエラーです。
デバッグの最中にPICkit3の不具合で作業を中断するのは、(『精神の鍛練を心掛ける』とは言え)やっぱり効率が悪く、なかなかデバッグが進みません(<==言い訳)。
調べてみると、これはMPLABXのバグらしく、Versionを3.55に戻すと良くなるのだそうです。MPLABXのArchive(ここ↓)から3.55を持ってきて早速試してみました。
Downloads Archive | Microchip Technology Inc. | Microchip Technology Inc.
昨日の午後から3.55に替えたのですが、”A tool request has been waiting for・・・”というエラーは出なくなりました。
(パチパチパチ~ )
先達の知恵、おそるべし!(同様に、このblogの情報が少しでも皆さんのお役に立つことを願います。)
デバッグ作業がようやく進みだしました。
RUNコマンドを送ると、指定した関数が走り出す・・・よし
BREAKコマンドを送ると、指定した関数を抜けてBreak_Loopが走り出す・・・よし
RESTARTコマンドを送ると、再び指定した関数が走り出す・・・よし
STOPコマンドを送ると、Main_Loopに戻る・・・よし
実は、関数の実行に問題が見つかって、BREAKコマンドを送っていないのにBreak_Loopが走ったり、STOPコマンドを送っていないのにMain_Loopに戻ってしまったり・・・その不具合のデバッグをしていました。原因は、『割り込み発生時に行われるレジスタ退避』に関して私の理解が不足していたことです。
以下マニュアルの抜粋
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
4.5 内容保存機能
割り込み動作に遷移する際、復帰時の PC アドレス値がスタックに保存されます。また、次に示すレジスタ値も自動的にシャドウ レジスタに保存されます。
• W レジスタ
• ステータス レジスタ (TO および PD を除く)
• BSR レジスタ
• FSR レジスタ
• PCLATH レジスタ
割り込みサービス ルーチンから通常動作に戻るとき、自動的にこれらのレジスタ値が回復されます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
割り込みから戻るときに、comm_main関数を呼び出したため、 ユーザ・プログラムへ戻ったときに上記レジスタの値が変化していました。ユーザ・プログラムの実行中もコマンド操作を可能にするための処置だったのですが・・・
少し不便ですが、ループ処理を伴うユーザ・プログラムは『ループ処理に所定の関数呼び出し(break関数)を加える』という条件を付けて、この問題の解決を図ることにしました。(<==ちょっと残念!)
次は、ユーザ・プログラムにBREAKポイントを設定してみます。
PICkit3が夏バテした
昨日(8/9)は関東地方も38度を超える猛暑日でした。
エアコンの無い(扇風機だけ ^_^; )部屋で開発しているので、室温もぐんぐん上がっていきます。
昨年も経験しているのですが、猛暑日になるとPICkit3がおかしくなります。昨日も3時過ぎに変なメッセージ(debug toolから1秒以上返事がないとかなんとか)が出て、デバッグできなくなってしまいました。orz
肝心かなめの関数呼び出しが上手く行かなくてカリカリしていた時だったので、当方の不快指数も一気に上昇して・・・
USBケーブルを引き抜きました。(<==怒りに任せてではありません)
PICkit3への通電を止めて、しばらく休憩です。
夕方まで待って再挑戦したのですが、直ぐにデバッグできなくなったので諦めました。
今朝は気温も低く(<==29度 ^_^;)、PICkit3も快調です。
ring_bufferを使ったデバッグ・ログでプログラムの動作を追いかけてみると・・・
80 01 8A 10 01 11 12 13 14 21 15 18 19 16 17 1A
01 8B 20 01 8A 10 01 11 12 01 8C 21
御覧の皆様には意味不明のログ出力だと分かっていますが、開発の大きなステップをクリアした記録なので、うれしくてつい貼ってしまいました。
RUNコマンドを受け取って(8A)、コマンド処理を始めて(10~13)、スタックを保存して(14~19)、呼ばれた関数が走って(16~17)、ブレークして(8B)、再スタート(8A)して、ストップ(8C)した様子が、記されています。
(パチパチパチ~)
PICkit3を冷やしている間、当方も頭を冷やしていて思いつきました。
『そうか、スタック操作中は割り込み禁止にしないといけないんだ!』
昨日動かなかった原因は、スタック操作中の割り込みだったのではないか?と考えています。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
見つけた不具合をデバッグしている最中に今日も出てしまいました。
これが出ると、作業できません。
”Programming/Verify complete
Running
A tool request has been waiting for more than a second. The debug tool will try to service the request within another second. After that the request will be rejected.
A tool request has been rejected because it could not be serviced within the two second timeout period.”
う~む、昨日より早く出るようになった。やっぱり夏バテだな。orz
今年の夏は『精神の鍛練』に努めます。
関数を固定アドレスに配置してみた
目指しているのは、ユーザ・プログラム(HEXファイル)をFlashメモリに書き込んで、ユーザが定義した関数を呼び出すことです。
HEXファイルを読み取り、Flashメモリに書き込むところまで出来ました。
あとは、書き込んだFlashメモリ上のアドレスを関数コールして、リターン出来れば・・・
本当に上手くできるのか?その実現性は未だ不明です。(^_^;)
関数呼び出しのテストをやりやすくするため、予め用意したtest_func()を呼び出してみることにしました。その関数を固定アドレスに配置できれば都合が良いのですが、どうすれば関数を固定アドレスに配置できるのか?
取り敢えずの思い付きを試してみると・・・
void test_func(void) @ 0x900
{
unsigned char loop;
while( break_flag )
{
loop++;
}
loop = 0;
}
ビンゴ~
簡単に実現出来てしまいました。
ーーーーーーーーーーーーーーーーーーーーーーーーーー
後で、『XC8 C Compiler User's Guide』を調べてみると、 5.8.4 Changing The Default Function Allocationの項に”absolute function”として説明されていました。
『知識は後から着いてくる』(<==基本的な開発ポリシー)
MPLABXの不具合が解決した
意外な結末でした。
comm.cを組み込むとMPLABXの動作がおかしくなることが分かって、調査は一気に進みました。先ずはcomm.cのコードの殆どをコメント・アウトして試してみると 問題なし(まぁ当然の結果です)。前半分のコメントを外しても問題なし(これで後半分に絞られました)
これを繰り返して不具合が再現する箇所を絞り込んで行くと・・・
以下の行(これ↓)に辿り着きました。
short stack[16];
変数名をstackからstack_buffに変更すればO.K.だと分かりました。
試しにmain.cに以下の記述を加えると不具合が再現しました。
int stack;
void main(void)
{
stack = 0;
コンパイル・エラーにならないのですが、stackという変数名がMPLABXの不具合を引き起こしていたようです。
やれやれ・・・