• ベストアンサー

PICマイコンのプログラムカウンタの操作法は?(C言語)

HI-TechのPICC PRO 9.65を使ってPIC16F877Aのプログラミングをしています。 しかし、最近マイコンの動作が不安定になり、突然プログラムが暴走したりするので、プログラムカウンタに問題があると疑っています。 昔、アセンブラでプログラムしていた頃はPCLATHに書き込んでからPCLに書き込んだり、ORG命令などで対処していましたが、今回初めてPICCを導入したので対処の仕方がわかりません。 またCコンパイラによっては自動でPCLATHを繰り上げてくれるようなのですが、PICCの場合はどうなのでしょうか。 hexを除いてみると0x0800のあたりもびっしりコードでうまっているのですが。。。 ちなみに asm("ORG 0x0800"); などのようにC言語の中にアセンブラで記述してもうまく解決できませんでした。 PCLATH = PCLATH + 0b000?????; とか色々やってみたのですがだめでした。 そもそもヘッダやインクルードの内容がどの番地に書き込まれているかを調べる良い方法はないでしょうか。 1.PICCはPCの操作を自動でやってくれているのか 2.もしそうでなければどのようにして解決すればよいのか で宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • bug_bug
  • ベストアンサー率78% (36/46)
回答No.3

1.PICC(コンパイラ)はPCの管理を行いません。 2.暴走の原因を最近プログラミングしてしまったものと見受けられます。 PIC16Fxxxのアーキテクチャの問題ですが、内部にPC用の専用スタック(LIFO)が存在します。 アセンブラ上でCALL(関数呼び出し)が発生した場合、現状のPCカウント値を専用スタックへPUSHし、return命令時に自動でPOPします。 但し、このスタックはデバイスに拠りますがリングバッファとして大概8層程度しかありませんので、PICCを使って関数コールを8層以上掛けた場合容易に上書きされてしまいます。 C言語上で確認が可能です。関数コールを連続してスタック数以上呼んでいませんか? 正確なPCスタック数はMicrochipのサイトからデータシート内の記述で確認が可能です。 問題部の記述が無いので憶測ですが、知らずに使うと簡単に暴走する部分ですので。たぶんココじゃないかなぁ?

d3msk8j
質問者

お礼

遅くなりました、ありがとうございます。 PIC16F877Aのスタックは物理的に8層までです。アセンブラのときは8層も使わなかったためスタックのことはすっかり忘れていました。ありがとうございます。 本日シミュレーターで1ステップずつ確認してみましたが、0x0000番地に急に飛んでしまうという問題の箇所に差し掛かるまでに、”C言語の関数は”3~5層しか呼んでいませんでした。 ですがコンパイルされたアセンブラリストを見ると、どうもひとつの関数のために何度かcall命令が生成されているので、C言語としては3層でもアセンブラ上では8層を超えている可能性がありそうです。。。正確に何層かは簡単には数えられなさそうです。 ちなみにMPLAB-IDEでは、C言語としてのスタック数はメニューからView-HardwareStackでみれたのですが、アセンブラのスタック数を見られるはずのView-CallStackのとこはなぜか灰色でクリックできません。なので明日かあさってにはなんとか手動で数えてみます。 これで数えてみてもし9層目をcallしていたらbug_bugさんには非常に感謝しなければいけないですね。。。ありがとうございます。調べるので少々お待ちください。 あと参考程度なのですが、0x0000番地に急に飛んでしまうという問題の箇所が、アセンブラリスト上では実は 2000 (CALL 0) となっていることがわかりました。そのまますぎて笑えるのですが、「call 0」とかいうこんな明らかに間違っているコンパイルをするというのは、無理に9層目をcallしようとして起きたという理解でいいんでしょうか。? このようなことを何か経験された方がいらっしゃったら引き続き教えてください>< もう表題と関係ないのでスタック数のことが正式に解決しましたら質問し直します。 bug_bugさんありがとうございました。

d3msk8j
質問者

補足

アセンブルリストで何層スタックしているかを数えてみましたが、0x0000番地に急に飛んでしまう問題の箇所ではスタックは全くオーバーフローしていませんでした。 そのかわり、0x0000番地に飛んだときにスタックはリセットされないままですので、プログラムの2周目か3周目でオーバーフローしていることがわかりました。 つまりなぜ”CALL 0”という変な命令が生成されてしまったかを解決しないといけないようです。

その他の回答 (3)

  • bug_bug
  • ベストアンサー率78% (36/46)
回答No.4

call 0 がコンパイラによって生成されるとは考えにくいので、MPLAB上の逆アセンブルリストを参照しているのであればconst値などのデータセクションにPCが飛んでしまっているのかもしれません。 逆アセンブルリストでプログラムROM上のアドレスさえ確認できれば、.mapファイルを参照し何が格納されているのか確認できますね。 仕様が不明なのでちょっと解答は難しいですが、割り込み発生時や、割り込み処理での要因別ブランチの関数コールなどでもPCスタックは行われるので注意が必要です。 とりあえず思いつくトコだけ・・・。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

C18やC30は、PIC16Fでは使えません。 他のコンパイラだと「SDCC」とか「CCS C/PCM」とか「FED-C」とかでしょうか。 c2cと言うのもあるみたいですが、Linux版のみ無料のようです。 http://ww2.tiki.ne.jp/~maro/old/PIC/C2C/ と思ったらc2cは入手不能になってました。 私は16F84しか書いたことないのでPCLATH対応については未知ですが、上記のc2cのアセンブルリストを見る限りは他のコンパイラでも対応している可能性が有ります。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

PICCには詳しくないんですが、とりあえずPC系の誤動作を疑うならアセンブルリストを取ってコードを確認してみてはどうでしょうか。 PICC-LITEと同じなら-ASMLISTで取れると思います。 実際上のメモリの配置アドレスは、リンカでマップファイルを作成する必要があります。調べてみてください。 なんにしても無理やりPCLATHを変更するのはC言語として矛盾が生まれるで無理があると思います。

d3msk8j
質問者

お礼

ありがとうございます。 アセンブルリストというものを知りませんでした。。。 いい忘れてましたがPICCはMPLABIDEと統合して使っていましたので、探してみたところMPLABのViewメニューのDisassemblyListingで見れました。 これでどの番地にどの関数が書いてあるか一目でわかりました、ありがとうございます。 で早速問題を調べてみましたが、シミュレータで見てみてもやはりreturn命令などの後にいきなり0x0003番地に戻されたりしているのでPC関連の問題な気がします。しかしどう対策するのかわかりません。。。 マップファイルやらでメモリの配置を触ったところで解決できる自信がありませんが一応今調べてみています。一応それぞれの関数はページをまたがない様に配置してくれていました。 あきらめてC18やC30に移行してみたくなっていますがこれらはPCの問題はないのでしょうか。。。

関連するQ&A