概要
今回は、WDTモジュールの使い方をご紹介します。
WDTとはWatchDog Timerの略でソフトウェアがWDTを定期的にクリアしないと、デバイスがリセットされます。これにより、システムソフトウェアが正常に動作していない場合に、それを検出することができます。
dsPIC33AKシリーズには似た機能として「DMTモジュール」が搭載されていますが、その機能については次回の記事で説明いたします。
・独立した動作モードとスリープモード用のカウンター
・動作モードカウンターに別のクロック源とポストスケーラを使用可能
・最大32種類の設定可能なタイムアウト期間
・動作モードとスリープモードカウンターに独立した5ビットポストスケーラ
・ハードウェアおよびソフトウェアで有効化可能
・窓付きWDTオプション – ソフトウェア設定ビットで制御する4つのウィンドウサイズ
今回は基本的な使い方から実践的な使い方まで紹介します。
関連記事
| 記事 | リンク | |
| 第1回 | dsPIC33AKシリーズについて | dsPIC33Aシリーズに関して – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第2回 | 開発ボード、コンフィグレーション設定、クロック設定について | dsPIC33AKシリーズ②開発ボード,コンフィグレーション設定,クロック設定について – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第3回 | CPU性能について | dsPIC33AKシリーズ③CPU性能について – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第4回 | FPU性能について | dsPIC33AKシリーズ④FPU性能について – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第5回 | DSPについて | dsPIC33AKシリーズ⑤DSPについて – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第6回 | タイマー1割り込みの使い方 | dsPIC33AKシリーズ⑥Timer1割り込みの使い方 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第7回 | PMUの使い方 | dsPIC33AKシリーズ⑦PMUの使い方 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第8回 | 高速ADCの使い方 | dsPIC33AKシリーズ⑧高速ADCの使い方 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第9回 | 高速OPAMPの使い方 | dsPIC33AKシリーズ⑨高速OPAMPの使い方 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第10回 | DMAモジュールの使い方 | dsPIC33AKシリーズ⑩DMAモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com) |
| 第11回(本記事) | WDTモジュールの使い方 | |
| 第12回 | DMTモジュールの使い方 |
開発環境
開発環境を以下に示します。
今回はどちらのCPUボードでも動作いたします。
| 項目 | 値 | リンク |
| ベースボード | dsPIC33A CURIOSITY PLATFORM DEVELOPMENT BOARD | dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com) |
| CPUボード(EV68M17A) | EV68M17A – dsPIC33AK128MC106 Motor Control DIM | dsPIC33AK128MC106 Motor Control Dual In-Line Module (DIM) Information Sheet (microchip.com) |
| CPUボード(EV02G02A) | dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | Microchip Technology |
| 統合開発環境 | MPLAB X IDE v6.20 | MPLAB® X IDE | Microchip Technology |
| コンパイラ | MPLAB XC DSC v3.10 | MPLAB® XC DSC Compiler | Microchip Technology |

WDTブロック図
以下にWDTのブロック図を示します。基本的には従来のdsPIC33CKシリーズと大きな変化点はありません。
WDTを有効化すると入力クロックのカウントアップを開始し、カウンタにリセットがかからないままカウントの最大値に到達すると、デバイスがリセットされます。

WDTレジスタとコンフィグフューズ
以下にWDTレジスタとその説明を示します。
| レジスタ名 | ビット名 | 説明 |
| WDTCON | ON | WDTモジュールの有効化/無効化 |
| WINSIZE | ウィンドウサイズ | |
| RMPS | RUNモード時のクロックプリスケーラ | |
| RMCLK | RUNモード時のクロック選択 | |
| SMPS | スリープモード時のクロックプリスケーラ | |
| WINDIS | ウィンドウモードの有効化/無効化 |
なおWDTはコンフィグでも設定が可能です。基本的な動作はレジスタで設定する場合と同一ですが、起動時から動作を開始するため、ペリフェラルなど初期化中にもリセットを行う必要が有ります。
コンフィグで設定された値はソフトウェアによって上書きすることが可能です。
| 設定項目 | 値 | コメント |
|---|---|---|
| FWDT_WINDIS | ON | ウォッチドッグタイマウィンドウ有効ビット(ウォッチドッグタイマは非ウィンドウモードで動作します) |
| FWDT_SWDTMPS | PS2147483648 | スリープモードウォッチドッグタイマポストスケーラ選択ビット(1:2147483648) |
| FWDT_RCLKSEL | BPRC256 | ウォッチドッグタイマクロック選択ビット(WDT実行モードはBFRC:256を使用) |
| FWDT_RWDTPS | PS2147483648 | 実行モードウォッチドッグタイマポストスケーラ選択ビット(1:2147483648) |
| FWDT_WDTWIN | WIN25 | ウォッチドッグタイマウィンドウサイズ選択ビット(WDTウィンドウはWDT期間の25%) |
| FWDT_WDTEN | HW | ウォッチドッグタイマ有効ビット(WDTはハードウェアで有効) |
| FWDT_WDTRSTEN | ON | ウォッチドッグタイマリセット有効ビット(WDTイベントはリセットを生成します) |
WDTウィンドウ動作
Watchdog Timerにはオプションのウィンドウモードがあり、WINDIS = 0ビット(WDTCON[0])で有効にできます。このモードでは、WINSIZE[1:0]ビットで指定されたウィンドウ時間内でのみクリアされる必要があります。

動作確認①(Windowモード 無し)
ソースコード
インクルードファイル
コンフィグレーションファイル、クロック設定ファイルは以下のファイルをインクルードしてください。
■コンフィグレーションファイル (config.h)
■クロック設定ソースファイル(Clock_Driver.c)
■クロックヘッダーファイル(clock_driver.h)
ソースコード全体
以下のコードを実行すると、起動後8秒後にCPUリセットが発生します。
//ClrWdt(); のコメントを削除するとWDTのクリアが行われ、CPUリセットは発生しません。
#include <stdio.h>
#include <stdlib.h>
#include <dsp.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"
int main()
{
/*-----------------------------------------------------------------------*/
/*初期化*/
/*-----------------------------------------------------------------------*/
vdg_Clock_Set_Register();
WDTCONbits.RMCLK = 3u; //LPRC 32kHz
WDTCONbits.RMPS = 12u; //8.192s
WDTCONbits.WINDIS = 1u; //Window 無効化
WDTCONbits.ON = 1u;
Nop();
/*----------------------------------------------------------------------------*/
/*メインルーチン*/
/*----------------------------------------------------------------------------*/
while(1)
{
//ClrWdt();
}
}
動作確認①(Windowモード 有り)
ソースコード
ソースコード全体
このコードを実行するとWDTが有効化され、約500ミリ秒後にClrWdt();が実行されます。しかし、このタイミングがウィンドウの外にあるため、タイマーはリセットされません。その結果、起動後1秒後にCPUがリセットされます。
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "peripheral_init.h"
#include "BoardSupportPackage.h"
#include <dsp.h>
uint32_t Timer;
int main()
{
/*-----------------------------------------------------------------------*/
/*初期化*/
/*-----------------------------------------------------------------------*/
vdg_Clock_Set_Register();
PR1 = 100000;
T1CONbits.ON = 1;
T1CONbits.TCKPS = 0;
IFS1bits.T1IF = 0;
IEC1bits.T1IE = 1;
IPC6bits.T1IP = 3;
WDTCONbits.RMCLK = 3u; //LPRC
WDTCONbits.RMPS = 10u; //1.024sec以内
WDTCONbits.WINDIS = 0u; //ウィンドウ有効化
WDTCONbits.WINSIZE = 3u; //75%
WDTCONbits.ON = 1u;
INTCON1bits.GIE = 1;
Nop();
/*----------------------------------------------------------------------------*/
/*メインルーチン*/
/*----------------------------------------------------------------------------*/
while(1)
{
Timer = 500;
while(Timer > 0) {;}
ClrWdt();
}
}
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void)
{
if (Timer > 0 ){Timer --;}
IFS1bits.T1IF = 0u;
}
Timer の値を以下のように変更すると、ウィンドウ内でWDTのクリアが行われるため、CPUリセットは発生しなくなります。
Timer = 800;
記事についての注意点
本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。

コメント