新・ウォッチドッグタイマを使ってみる ~PSoC 40xx 編~ [PSoC]
前回の記事「新・ウォッチドッグタイマを使ってみる ~PSoC 42xx 編~」では、 PSoC 42xx を題材に Interrupt Service Routine (ISR) を自動生成させて楽をする方法をさぐりました。 今回は、 PSoC 40xx で試してみます。
WDT 設定は簡易版
PSoC 40xx の低速クロック設定ダイアログにも Watch-Dog Timer (WDT) 設定が追加されました。 ただし、 PSoC 40xx は、 PSoC 42xx とは異なり、 WDT カウンタを1系統しか持っていません。 そのため、配置されている設定ブロックも一つだけです。
また、16ビットのフリーランニングカウンタが使用されている所も異なっています。 このカウンタの値が MATCH レジスタの値と等しくなったら割り込みが発行されます。 デフォルトでのカウンタの周期は 65536/40kHz=1.6sec となります。
MATCH レジスタとの比較では、上位ビットの比較結果を無視する事によって、割込みの周期を短く設定することが出来ます。 例えば、上位2ビットを無視すると周期は 16384/40kHz=0.4sec になります。 ドロップダウンリスト "Period" で周期を設定して、何ビットを無視するのか決定する事ができます。 この実験では、約 0.5 秒周期で割り込みを発生させたかったので、 409.6ms を使用します。
WDT 設定部では、動作モードを "Free Running Timer" と "Watchdog (w/ Interrupt)" から選択する事ができます。 これら二つのモードには、ウォッチドッグリセットが有効になるか無効になるかの違いが有ります。 "Free Running Timer" ではウォッチドッグリセットが無効に、 "Watchdog (w/ Interrupt)" ではウォッチドッグリセットが有効になります。 つまり、 "Free Running Timer" を使うと餌をやる手間がかかりません。 どちらにしても、フリーランニングカウンタの周期で割り込みフラグがセットされるところは同じです。 また、チェックをはずして WDT 設定そのものを無効にするとウォッチドッグリセットが無効になります。
ウォッチドッグリセット機能は、フリーランニングカウンタが MATCH レジスタの値と一致するイベントが3回発生するまでにウォッチドッグに餌をやらないとリセットが発生する仕組みです。 餌をやるためには、割り込みフラグをクリアします。 割込み機能を使う場合、通常は割込みルーチン内でフラグをクリアします。 そのため、メインループが暴走しても割り込みさえ正しく処理できればウォッチドッグリセットは発生しません。 どうやら、割込み機能も使用する場合、ウォッチドッグとしての機能は期待できないようです。
ウォッチドッグリセットの機能は、 Technical Reference Manual (TRM) によるとリセット直後は有効になっています。 ところが、 PSoC Creator が生成しているコードでは、デフォルト状態で無効になっているように見えます。 これは、 "Cm0Start.c" ファイルの中でリセット直後にウォッチドッグリセットを無効にしているのが原因でした。 ウォッチドッグリセットの機能から考えると、デフォルトでは有効にすべきですが、そうはなっておらず、デフォルトの状態を設定することも出来ないように見えます。 ウォッチドッグリセットを使う時には、注意が必要です。
ISR はあるけれど
PSoC 40xx でも、 "CYLFClk.c" に Interrupt Service Routine (ISR) が作成されています。 ところが、 ISR 設定部が存在しないのに加えて、割込みベクタとして設定もされていないので、デフォルトのままでは使用できません。 そのため、従来通りに Global Signal コンポーネントの出力を Interrupt コンポーネントに接続して割込み機能を実現します。
ソースコードが簡単になったかな?
ウォッチドッグタイマを使った「Lチカ」の完成です。 ソースコードは、以下のようになりました。
#include <project.h> void Wdt_Callback(void) { Pin_LED_Write(~Pin_LED_Read()); } int main() { // Initialize WDT interrupt Wdt_int_StartEx(CySysWdtIsr); CySysWdtSetInterruptCallback(Wdt_Callback); CySysWdtUnmaskInterrupt(); CyGlobalIntEnable; /* Enable global interrupts. */ /* Place your initialization/startup code here (e.g. MyInst_Start()) */ for(;;) { /* Place your application code here. */ } }
初期設定部分で使用している関数 CySysWdtUnmaskInterrupt() で、ウォッチドッグタイマによる割り込みを受け付けます。 コード量は、多少減ったんじゃないかな?
今回の記事で使用した手法は、ウォッチドッグタイマのオーバーフローを利用しています。 これは、割込みが発生するたびに MATCH レジスタを書き換えていた以前の記事とは異なり、周期の解像度で劣ります。 もっと解像度を上げたい場合には、自前で ISR を記述する必要があるでしょう。
プロジェクトアーカイブ
この記事で作成したプロジェクトは、このファイルの拡張子を "zip" に変更すると再現できます。
参考文書
- PSoC 4 Low-Frequency Clock (cy_lfclk), Version 1.0
- 現在の PSoC Creator では、 "Watchdog Timer" などの LFCLK を利用した機能は、 cy_lfclk という独立したコンポーネントにまとめられています。 "Watchdog Timer" の使い方などの詳しい情報は、この文書に書いてあります。
- PSoC 4000 Family: PSoC 4 Architecture Technical Reference Manual (TRM)
- PSoC 40xx の内部構成について書かれた文書です。 残念ながら、ウォッチドッグについての記述は充実しているとは言い難い状態です。
コメント 0