Timer割り込み(コンペアマッチタイマー CMT)

# はじめに
コンペアマッチタイマー CMTで行うTimer割り込みの設定諸々についての記述．マイコンボードはGR-CITRUSとする．ハードウェアマニュアルの参考先はHM ＊.＊.＊と表記する（例：HM 3.3.4ならばハードウェアマニュアルの3.3.4節を参考）．

資料（必需品）
・ [RX63Nグループ、RX631グループ ユーザーズマニュアル](https://www.marutsu.co.jp/contents/shop/marutsu/datasheet/R5F563.pdf)
・ [GR-CITRUS回路図](https://www.renesas.com/jp/ja/doc/gr/gr-citrus/citrus-1.0.pdf)

# Timer割り込みとは
カウントダウンタイマーがクリアされる時に，任意のプログラムを実行する．

# Timer(CMT)割り込み設定
CMTの初期化と割り込み関数の作成を行う．

### 初期化関数

流れ
1. CMT有効化
2. CMTの設定
3. 割り込み優先度の設定
4. 割り込み許可

```c:"hwsetup.c"

extern void HardwareSetup(void);
void GPIO_init(void);
void Clock_init(void);
void CMT0_init(void);

void HardwareSetup(void)
{
	GPIO_init();
	Clock_init();
	CMT0_init();
}
```

```
/*=================================
 * 関数名 : CMT0_init
 * 機能 : CMT0の初期化
 * 引数 : なし
 * 戻り値 : なし
 * 備考 :設定周期 :1ms 割り込み優先度:4
 * ===============================*/
void CMT0_init(void)
{
	/*=== プロテクト解除 ===*/
	SYSTEM.PRCR.WORD = 0xA502;
	/*=== CMTを有効化 ===*/
	MSTP(CMT0) = 0;
	/*=== プロテクト ===*/
	SYSTEM.PRCR.WORD = 0xA500;
	/*=== CMT動作停止 ===*/
	CMT.CMSTR0.BIT.STR0 = 0;
	/*=== CMT設定 ===
	 * クロック選択 : PCLK/8 = 6MHz
	 * CMT割り込み許可
	 * ===========*/
	CMT0.CMCR.BIT.CKS =0;
	CMT0.CMCR.BIT.CMIE = 1;
	/*=== カウントリセット ===*/
	CMT0.CMCNT = 0;
	/*=== 周期カウント設定 ===
	 * 設定周期 : 1ms
	 * CMCOR = 設定周期[s]*PCLKB[Hz]/分周比-1
	 * ================*/
	CMT0.CMCOR = 5999;
	/*=== CMT動作開始 ===*/
	CMT.CMSTR0.BIT.STR0 = 1;
	/*=== 割り込み優先度設定 ===*/
	IPR(CMT0,CMI0) = 4;
	/*=== 割り込み許可 ===*/
	IEN(CMT0,CMI0) = 1;
}

```

### 割り込み関数

```c:icu_cmt.c
#include"iodefine.h"
#include"vect.h"

#define LED PORTA.PODR.BIT.B0
#define LED_ON 1
#define LED_OFF 0

void LightLED(void)
{
	if(PORTC.PIDR.BIT.B0 == 0)
	{
		LED = LED_ON;
	}else{
		LED = LED_OFF;
	}
}
```
新たにファイルを作成して，割り込みによってやりたいことを記述した関数を作成する．この関数の宣言は既存のvect.hの中でやることになる．


```c:vect.h
// CMT0 CMI0
//#pragma interrupt (Excep_CMT0_CMI0(vect=28))
//void Excep_CMT0_CMI0(void);
#pragma interrupt (LightLED(vect=28))
void LightLED(void);
```
vect.hの//CMT0 CMI0直下の2行をコメントアウトして，自作した関数名に書き換える．割り込み関数を既存の` Excep_CMT0_CMI0`にする場合は，/generate/intprg.cに用意されている関数内にプログラムを書く．

多重割り込みを行う場合は，enableを追加するらしい．

```c
#pragma interrupt ((割り込み関数名)(vect=(ベクタ番号)),enable)
```

### 詳細

##### 1. CMT有効化

```
SYSTEM.PRCR.WORD = 0xA502;
```
**プロテクト解除**
HM 13.1.1より，保護するレジスタへの書き込み許可を選択する．`PRCR`は16bit構成で以下のような内容である．`WORD`で一括で設定している．
b0 > 0 :クロック発生回路関連レジスタへの書き込み禁止
b1 > 1 :動作モード、消費電力低減機能、ソフトウェアリセット関連レジスタへの書き込み許可
b2 > 0 :予約ビット
b3 > 0 :LVD関連レジスタへの書き込み禁止
b7-4 > 0 :予約ビット
b15-8 > A5 : PRCキーコードビット 

```
MSTP(CMT0) = 0;
```
**モジュールストップ解除**
HM 11.4より，レジスタの読み出し書き込みができる状態にする必要がある．`=0`で解除となる．

```
SYSTEM.PRCR.WORD = 0xA500;
```
**プロテクト**
HM 13.1.1より，保護するレジスタへの書き込みを禁止する．


##### 2. CMTの設定

```
CMT.CMSTR0.BIT.STR0 = 0;
```
**CMT動作停止**
HM 28.2.1より，CMT0.CMCNTカウンタのカウント動作を停止する．

```
CMT0.CMCR.BIT.CKS =0;
CMT0.CMCR.BIT.CMIE = 1;
```
**CMT設定**
HM 28.2.3より，`CKS`レジスタで，周辺モジュールクロック（PCLK）を分周して得られる分周クロックからCMCNTカウンタに入力するカウントクロックを選択する．後述の周期設定に合わせて適切な分周を選ぶ．`CMIE`レジスタで，割り込みの許可をする．

```
CMT0.CMCNT = 0;
```
**カウントリセット**
HM 28.2.4より，CMCNTの初期値を0にする．CMCNT カウンタの値が CMCOR レジスタの値と一致すると，CMCNT カウンタは “0000h” になる．このとき，コンペアマッチ割り込みが発生する．

```
CMT0.CMCOR = 5999;
```
**周期カウントの設定**
HM 28.2.5より，CMCORの値を指定して，割り込み周期を設定する．コンペアマッチタイマーは1/(PCLKB[Hz]/分周比)秒のタイミングでCMCNT カウンタをカウントアップをしていき，CMCOR レジスタの値と一致すると，CMCNT カウンタは “0000h” にする．このとき，コンペアマッチ割り込みが発生する．カウント数xカウントクロックの周期が割り込み周期となる．
CMCORの値は，以下の数式で値を決定する．

```math
CMCOR = 設定周期[s]*PCLKB[Hz]/分周比-1
```
この時，16bitタイマーなので，CMCORに設定できる値は0xFFFFないである必要がある．設定周期に合わせて分周比を調整する． 

![CMT.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520158/5fe79e5d-3a6d-bf55-9d3b-6580aeb665cb.png)


```
CMT.CMSTR0.BIT.STR0 = 1;
```
**CMT動作開始**
HM 28.2.1より，CMT0.CMCNTカウンタのカウント動作を開始する．

##### 3. 割り込み優先度の設定

```
IPR(CMT0,CMI0) = 4;
```
HM 15.2.3より，対応する割り込み要因の優先レベルを選択する．優先度は0から15まで指定できて，値が大きいほど優先度が高くなる．0は高速割り込みに設定している場合のみ割り込み可能である．

##### 4. 割り込み許可

```
IEN(CMT0,CMI0) = 1;
```
HM 15.2.2より，割り込み要求先に割り込み要求を出力する．

# 端書き
割り込みを任意期間だけする場合は，setup.cで割り込み許可をしないでプログラム上で許可を行う．

```
#define CMT1_START IEN(CMT1,CMI1) = 1
#define CMT1_STOP IEN(CMT1,CMI1) = 0
```



# 参考文献

- RX220で1ms周期のタイマを作成してLチカ https://qiita.com/ekd/items/6015c1022411b23f15d1
- RX631開発 Timer割り込み - CCWO https://ccwo.hatenablog.jp/entry/2016/08/18/023400