PSoC 4200DS でウォッチドッグタイマをウォッチドッグとして使う

**PSoC 4**には、ウォッチドッグタイマ（Watch Dog Timer: WDT）というブロックがあります。この記事では、WDTをウォッチドッグとして使う方法を**PSoC 4200DS**を題材に考えます。

## そもそもウォッチドッグとは、

ウォッチドッグというのは、番犬の意味です。この番犬は、餌があればおとなしいのですが、餌をやり忘れると吠えてきます。それは、本当に番犬なのか？一般的には、吠えられた**MCU**は、リセットがかかります。この仕組みを使うと、エサ係が何らかの事情（通常は暴走）で餌を持ってこなくなった非常事態を検出してリセットをかけることができます。
ウォッチドッグの仕組みでは、ある決められた時間までに餌をもらったかどうかを判別する必要があります。この時間を測定するため、数十kHzの内蔵クロックを数える比較的長周期のタイマを装備しています。

## ウォッチドッグタイマの用途

このような長周期タイマは、一般的な周期割り込みとしても使い勝手が良いので、**PSoC 4**では、多くの場合、ウォッチドッグタイマを周期タイマとして使用しています。初期の高性能**PSoC 4**の場合には、**WDT**の中にタイマカウンタが3系統も存在し、それぞれが周期タイマ割り込みとしてもウォッチドッグリセットとしても使えるようになっていました。

![GS004451.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224737/67f6a425-ca83-a389-8b33-718bb7d86212.png "Figure 12-2. Watchdog Timer Internal Block Diagram")
PSoC 4100M/4200M Family PSoC 4 Architecture TRM, Document No. 001-95223

ところが、最近の**PSoC 4**では、もっと簡素な作りのウォッチドッグタイマが使われるようになりました。

![GS004452.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224737/672bc687-6a4e-167f-2e84-e454acd08f4e.png "Figure 12-1. Watchdog Timer Block Diagram")
PSoC 4200D Family PSoC 4 Architecture TRM, Document No. 001-98108

いや、なんか省略しすぎでしょう。
この図が描かれた文章には、16ビットのアップカウンタで出来ていて、MATCHレジスタとMASKレジスタで希望の周期が得られると書いてあります。

このウォッチドッグタイマは、リセットに使ってしまうと、事実上周期タイマには使えなくなります。周期タイマとしての使用例はあふれているので、この記事では、この簡素なウォッチドッグタイマをウォッチドッグとして使う方法を提供します。

## 回路図

![GS004450.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224737/3c077af5-35d7-e191-f913-16e202dc2ca3.png "Schematic")

ウォッチドッグを使うのだから、回路図にウォッチドッグコンポーネントを配置して…なんてことはありません。回路図には、ウォッチドッグに特有なものは何も必要ありません。

回路図においてあるコンポーネントは、非常事態をエミュレーションするためのスイッチ入力とリセットの要因を表示させるための**UART**だけです。

![GS004457.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224737/f687ea37-6b63-68ad-4794-492b6a046b60.png "クロック設定")

代わりに必要なのは、クロック設定です。"Low Frequency Clocks"タブで"Timer (WDT)"にチェックを入れて有効にします。そして、"Mode"を"Watchdog (w/ Interrupt)"に設定してウォッチドッグリセットとウォッチドッグ割り込みを有効にします。このプロジェクトでは割り込みは必要ないのですが、このチップでは片方だけ有効にするという選択肢がありません。割り込みの方は、"Unmask"しなければ動かないので、この設定で問題ありません。

タイマの周期を819.2msにしたので、少なくとも３倍の時間、約2.4秒間エサをやらないとリセットがかかります。

## ファームウェア

ファームウェアにあるのは、`main()`関数のみです。

```C:main.c
#include "project.h"
#include <stdio.h>

int main(void)
{
    uint32 reason;
    char sbuf[64];
    
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    UART_Start();
    UART_UartPutString("\r\nHELLO WORLD\r\n");
    reason = CySysGetResetReason(CY_SYS_RESET_WDT | CY_SYS_RESET_PROTFAULT | CY_SYS_RESET_SW);
    strcpy(sbuf, "RESET REASON:");
    if (reason & CY_SYS_RESET_WDT) {
        strcat(sbuf, " WDT");
    }
    if (reason & CY_SYS_RESET_PROTFAULT) {
        strcat(sbuf, " FAULT");
    }
    if (reason & CY_SYS_RESET_SW) {
        strcat(sbuf, " SW");
    }
    strcat(sbuf, "\r\n");
    UART_UartPutString(sbuf);
```

前半では、 リセット要因を調べて**UART**に出力します。

```
HELLO WORLD
RESET REASON:

HELLO WORLD
RESET REASON: WDT
```

リセット要因に何も書かれていなければ、通常のハードウェアリセット。**WDT**と書かれていればウォッチドッグリセットがかかったことを示します。
このプロジェクト例では、他のリセット要因も検出できるようになっていますが、このプロジェクト例のままでは他のリセット要因は発生しないはずです。

```C:main.c
    for(;;)
    {
        /* Place your application code here. */
        if (Pin_SW1_Read()) {
            CySysWdtClearInterrupt();
        }
        CyDelay(100);
    }
}
```

後半では、メインループ内でウォッチドッグに餌をやっています。餌をやる条件は、スイッチ入力が"High"すなわちタクトスイッチが押されていない事です。タクトスイッチを押さずに放置していれば、ウォッチドッグリセットはかかりません。また、タクトスイッチを2.4秒間押しっぱなしにすると、ウォッチドッグリセットがかかります。

ウォッチドッグに餌をやるための関数が`CySysWdtClearInterrupt()`です。関数の名前からはウォッチドッグに餌をやるための関数だとはとても想像できませんが、ウォッチドッグ割り込みと共用している関係上しかたがありません。気に入らなければ、マクロを使って違う名前で呼び出せるようにしましょう。

このプロジェクト例では、100ミリ秒ごとに餌をやっていますが、あまり意味はありません。重要なのは、周期的にメインループの中で餌をやって、メインループがどこかで止まっていないかを監視させることです。

## GitHub リポジトリ
[noritan/Design364][Repository]


## 関連記事
[PSoC 40xx でウォッチドッグ・タイマを使ってみる][]
[新・ウォッチドッグタイマを使ってみる ~PSoC 42xx 編~][]
[新・ウォッチドッグタイマを使ってみる ~PSoC 40xx 編~][]


[新・ウォッチドッグタイマを使ってみる ~PSoC 40xx 編~]:https://noritan-micon.blog.so-net.ne.jp/2016-03-26
[新・ウォッチドッグタイマを使ってみる ~PSoC 42xx 編~]:https://noritan-micon.blog.so-net.ne.jp/2016-03-21
[PSoC 40xx でウォッチドッグ・タイマを使ってみる]:https://noritan-micon.blog.so-net.ne.jp/2014-05-24
[Repository]:https://github.com/noritan/Design364