Baumkuchen’s Workshop

バイオリンと電子工作、DIY、ジョギングなど。

データロガーの改善(ソフト編) PIC24Fの割り込みにはまる

ソフト編

 ハードが大体できたので、ソフトを作っていきます。PIC24F系は初めてなので、試行錯誤がいりそうです。

baum-kuchen.hatenablog.com

 セットアップ

 開発環境は、MPLAB X IDE v5.30を使っています。改善前のデータロガー用に、GSP受信、LCD表示ルーチン等途中まで作って一通り動くソフトがあるので、それを加工しながら作ります。

始めに、ツールのDashboardで、DeviceをPIC18F14K50からPIC24FJ64GB002へ変更し、Build実施。

あれ?何かエラーで、buildが全くできない。Dashboardをみてみると、どうもコンパイラが選択できていない。XC8コンパイラが選べない。

ひとしきり考えて挙句、なんだ、XC8コンパイラは8bit PIC用だ。PIC24F~ は、16bitなので対応していないということでした。早速、microchipのホームぺージから、XC16コンパイラをダウンロードして、Dashboardの設定もちゃんとして、Buildが動くようになりました。ただし、まだ、エラーの山ですが。

今まで、ずっと8bitの世界でした。PIC24Fから16bitなんですね。勉強になりました。ていうか、当たり前すぎて、参考にもなりませんかね。

f:id:Baum_kuchen:20200517142405p:plain

ヘッダーファイル

Buildは動くようになりましたが、エラーの山。PIC24FJ64GB002用のヘッダーファイルが見つからないって怒られてます。はて、Dashboardで設定したらパスを通してくれないのと思いながら、ヘッダファイルのありかを探します。

 C:\Program Files\Microchip\xc16\v1.50\support\PIC24F\h

で、これを読み込ませるように、Common include dirsに登録。ここで良いのかは、いろいろ試行錯誤して、見つけたので、本当にあってるのは分かりませんが。

でも、Deviceを設定したんだから、自動で設定して欲しいですね。

 f:id:Baum_kuchen:20200517141747p:plain

f:id:Baum_kuchen:20200517141731p:plain

割り込み

 さて、一通りセットアップできたようなので、PI24Fのデータシートをにらみならが、以前のソースからOscillator、I/O Port、A/D、UARTなどのレジスタ設定とかを修正していき、何とかBuildが通るようになりました。ここらへんは、8bit系も16bit系も大体同じだので、単なる力技でしょう。

また、今回は、PICのピン数も増えたので、In-Circuitデバッガーも使って行えるようにしました。 デバッグ時に内部のデータが見れるのは多いに助かります。

 

最初は、I/O portの設定とが間違ってないかチェックのため、お決まりのLEDチカチカのデバッグルーチンで作動。

結果、LEDがちゃんと点滅しました。うん? 何か変だ。まだ、点灯しかプログラムしていないのに。不思議だ(プログラムバグって大体不思議な動きをしますけどね)

ここで、早速、In-Circuitデバッガーの登場。Debugモードでbuildして、Debuger起動。MPLABのコンソールを見ると、起動したはずなのに、停止状態の表示(Continueボタンが点いている)。OutputのDebugger Consoleを見ると次の様な表示。

f:id:Baum_kuchen:20200517145627p:plain

確かに止まっている。(ということは、点滅は、PICが起動、停止(リセット)を繰り返していたためね、とこっちの原因は一応判明) メッセージを見ると

  __DefaultInterrupt, .LFE2, .isr ( ) @ Compiler generated location : 0x2f8

 とあるけど、意味不明。割り込みに関係してそうですが。

じゃあ、一回、割り込み禁止にしてみるか、ということで、唯一割り込み許可していたUARTの割り込みを一旦不許可にしてみると。----->止まらなくなった。

じゃあ、上流をたどって、UARTのハード的入力を固定(GPS受信器を外し、3.3V固定)として、ハード的には割り込みが入らない状態に。----->止まらなくなった。

ということは、UART割り込みが要因だけど、何故?

次に、UARTの割り込み処理ルーチンにブレークポイントを設定してDebug実施。

  ----->ブレークポイントで止まらない。

f:id:Baum_kuchen:20200517154152p:plain

不思議の3乗。原因はUARTの割り込みなのに、ブレークポイントで止まらないとは。

 

完全に行き詰った感あり。もう一度、データシートをよく見てみる。

7.1 Interrupt Vector Table
The Interrupt Vector Table (IVT) is shown in Figure 7-1.
The IVT resides in program memory, starting at location
000004h. The IVT contains 126 vectors, consisting of
8 non-maskable trap vectors, plus up to 118 sources of
interrupt. In general, each interrupt source has its own
vector.

うーん、なるほど。このPICには、割り込みベクターテーブルがあるのか。それぞれの割り込み要因毎にベクターがある・・・・。

あれ、UARTの割り込みベクターって、どう設定したっけ。何もしてない!。そもそも、どうやって指定するんだ?????

7.4.2 INTERRUPT SERVICE ROUTINE
The method that is used to declare an ISR and initialize
the IVT with the correct vector address will depend on
the programming language (i.e., ‘C’ or assembler) and
the language development toolsuite

データシートには、こう書いてあって、これじゃわからないではないか。要は、XC16コンパイラのマニュアルと格闘しろってこと?

割り込みルーチンの書き方

コンパイラのマニュアル(MPLAB_XC16_C_Compiler_Users_Guide.pdf)を読みました。マニュアルは、 C:\Program Files\Microchip\xc16\v1.50\docsに入っています。

Chapter 14. Interruptsの中に、14.3 Writing an Interrupt Service Routine があり、ここに書いてありそう。

ありました。割り込み処理の書き方。関数属性に、irq(irqid)を指定すれば良さそう。

The syntax of the interrupt attribute is:
__attribute__( (interrupt [(
     [ save(symbol-list)]
     [, irq(irqid)]
     [, altirq(altirqid)]
     [, preprologue(asm)]
    )]
) )

データシートのTABLE 7-2にベクターNo.があるんで、これを指定すればいいんですね。

f:id:Baum_kuchen:20200517160901p:plain

UART1の受信は、No.11なので、次の様に。

  void __attribute__( (interrupt(auto_psv,irq(11))) ) USART_getchar(void) 

 結局、ちゃんとベクタNo.を指定しないから、UART割り込みが別のベクター__DefaultInterrupt)に飛んでいって、それで、リセットが掛かっていたんですね。

Target Memory Viewからプログラムメモリの中をのぞくと、UART1の割り込みベクターに、__DefaultInterrupt(opcode= 0x2f8)がセットされているのが分かります。

f:id:Baum_kuchen:20200517165608p:plain

非常にクリアに原因が解ってスッキリしました。これも、16bit PICとしては当たりまえで、自分の勝手な思い違いが原因でしたが、コロンブスの卵と同じで、分かってしまえばあたりまえ、ただし、そこに行くまでが結局、問題なんですよね。

ベクターNo.が指定できない

全てが解決したかに思えましたが、ここから、また山がありました。・・・・       hardware_bsp/system.c:153:1: error: interrupt vector number 11 is not valid

とういエラーが出ます。irq(52)とすると問題なくbuildができます。11という数値が問題の様ですが、これでは、UART1のベクタが設定できないではないか。PIC24FJのデータシートを読んでも、118このベクターを設置できるとありますが、Fig 7-1には、Vector 0,1,52,53,54,116,117しか図示ていません。

f:id:Baum_kuchen:20200517205145p:plain

ひょっとして、この8個だけなの?と思って、54を設定しても同じくエラー。XC16のマニュアルを読んでも、よくわかりませんでした。*1

いいところまで来たと思ったのに。

 

マニュアルを読み進めると、14.4 Specifying the Interrupt Vectorという章があり。これかなと思いよみ進めると、

14.4.2 Interrupt Vector Tables
For tables of interrupt vectors by device family:
• In MPLAB X IDE, for newer versions of the compiler, open the Dashboard window and click on the Compiler Help button.

 との記述が。ボタンを押せ? うん、わかった。

 f:id:Baum_kuchen:20200517205657p:plain

 で、押してみました。とすると、

f:id:Baum_kuchen:20200517205843p:plain

こんな画面が開きました。いろいろドキュメントあります。ここに、

・Interrupt Vector Tables Reference - HTML

という項目があるので開くと、一覧表が。インタラプトベクターを指定すると記載があります。

f:id:Baum_kuchen:20200517210231p:plain

この名前どう使うのか? マニュアルにあるサンプルを見て、どうもこれは、割り込みルーチンの関数名にするということではないかと想像。つまり、 

  void __attribute__( (interrupt(auto_psv)) ) _U1RXInterrupt(void)

とすれば、良いということ?果たして、・・・

 正解

 でした。Debugerが止まることもなく、UARTの受信で、ちゃんと割り込み処理ルーチンに飛んできました。もちろん、ブレークポイントも有効に機能します。

終わりに

割り込み処理が動くようになり、長い旅がやっと終わった感じです。結局、ここまで、約1週間かかりました。疲れた。

振り返ってみると、教訓は、”8bitと16bitは違う”ことと、”マニュアルは細部までちゃんと読もうね”ですかね。

この記事が、PIC24Fを使おうと思っている方に、少しでも役に立ったら幸いです。

*1:今見てみると、14.4.1に詳しく書いてあるようです。斜め読みはいけませんね。