• R/O
  • HTTP
  • SSH
  • HTTPS

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

RL78/F14マイコンを使用したCAN通信/LIN通信のチェッカー


File Info

Rev. 85fcb496057f40f6bb6a30b02de357ea2efb6483
Tamaño 10,554 octetos
Tiempo 2016-07-17 11:16:45
Autor Yasushi Tanaka
Log Message

新規作成(ターゲットボード:ルネサスQB-R5F10PPJ-TB、CC-RL用)

Content

/*
 * CAN/LIN Checker for RL78/F13,F14
 *
 * Target: QB-R5F10PPJ-TB (RL78/F14, 100pin, 256KB ROM, 20KB RAM)
 * Author: Yasushi Tanaka
 *
 * [ DTCドライバ ]
 */

#include "common.h"
#include "iodefine.h"
#include "cpu.h"
#include "log.h"
#include "dtc.h"

/*
 * DTC
 * ハードウェア定数
 */
#define DTC_BUFFER_SIZE			((u2)(0x0050))
									/* DTCコントロールデータサイズ(ベクタ含む) */
#define DTC_UART0_RX			((u1)(10))
									/* DTC起動要因番号(UART0受信完了) */
#define DTC_UART0_TX			((u1)(11))
									/* DTC起動要因番号(UART0送信完了) */
#define DTC_UART1_RX			((u1)(12))
									/* DTC起動要因番号(UART1受信完了) */
#define DTC_UART1_TX			((u1)(13))
									/* DTC起動要因番号(UART1送信完了) */

/*
 * DTCコントロール・データ
 * オフセット
 */
#define DTC_CTRL0_OFFSET		((u1)(0x40))
									/* DTCベクタからコントロール・データ0へのオフセット */
#define DTC_CTRL1_OFFSET		((u1)(0x48))
									/* DTCベクタからコントロール・データ1へのオフセット */
#define DTC_DTCCR_OFFSET		((u1)(0))
									/* コントロール・データ先頭からDTCCRjへのオフセット */
#define DTC_DTBLS_OFFSET		((u1)(1))
									/* コントロール・データ先頭からDTBLSjへのオフセット */
#define DTC_DTCCT_OFFSET		((u1)(2))
									/* コントロール・データ先頭からDTCCTjへのオフセット */
#define DTC_DTRLD_OFFSET		((u1)(3))
									/* コントロール・データ先頭からDTRLDへのオフセット */
#define DTC_DTSARL_OFFSET		((u1)(4))
									/* コントロール・データ先頭からDTSAR(LO)へのオフセット */
#define DTC_DTSARH_OFFSET		((u1)(5))
									/* コントロール・データ先頭からDTSAR(HI)へのオフセット */
#define DTC_DTDARL_OFFSET		((u1)(6))
									/* コントロール・データ先頭からDTDAR(LO)へのオフセット */
#define DTC_DTDARH_OFFSET		((u1)(7))
									/* コントロール・データ先頭からDTDAR(HI)へのオフセット */

/*
 * SFR設定値(PER1レジスタ)
 */
#define RL78F_PER1_DTCEN		((u1)(0x08))
									/* DTC有効 */

/*
 * SFR設定値(DTCENiレジスタ)
 */
#define RL78F_DTCEN_DISABLE		((u1)(0x00))
									/* DTC起動禁止(全ビット) */

/*
 * SFR設定値(DTCEN1レジスタ)
 */
#define RL78F_DTCEN1_UART1_TX	((u1)(0x04))
									/* DTC起動許可(UART1送信完了) */
#define RL78F_DTCEN1_UART1_RX	((u1)(0x08))
									/* DTC起動許可(UART1受信完了) */
#define RL78F_DTCEN1_UART0_TX	((u1)(0x10))
									/* DTC起動許可(UART0送信完了) */
#define RL78F_DTCEN1_UART0_RX	((u1)(0x20))
									/* DTC起動許可(UART0受信完了) */

/*
 * SFR設定値(DTCCRjレジスタ)
 */
#define RL78F_DTCCR_SAMOD		((u1)(0x04))
									/* 転送元アドレスを加算 */
#define RL78F_DTCCR_DAMOD		((u1)(0x08))
									/* 転送先アドレスを加算 */

/*
 * SFR設定値(DTBLSjレジスタ)
 */
#define RL78F_DTBLS_ONE			((u1)(0x01))
									/* 1回の転送で8ビットまたは16ビットを転送 */

/*
 * SFR設定値(DTRLDjレジスタ)
 */
#define RL78F_DTRLD_ONE			((u1)(0x01))
									/* リピート・モードでリロードされる転送回数 */

/*
 * SFR設定値(DTDARjレジスタ)
 */
#define RL78F_DTDAR_SDR00L		((u2)(&(SDR00L)))
									/* UART0送信バッファレジスタ */
#define RL78F_DTDAR_SDR01L		((u2)(&(SDR01L)))
									/* UART0受信バッファレジスタ */
#define RL78F_DTDAR_SDR10L		((u2)(&(SDR10L)))
									/* UART1送信バッファレジスタ */
#define RL78F_DTDAR_SDR11L		((u2)(&(SDR11L)))
									/* UART1受信バッファレジスタ */

/*
 * DTC
 * ベクタ・テーブル&コントロール・データ領域
 */
static u1 dtc_buffer[DTC_BUFFER_SIZE + LOG_BUFFER_SIZE];
									/* DTC_BUFFER_SIZE + LOG_BUFFER_SIZE >= 0x0200を前提とする */
static SADDR volatile u1* dtc_vector;
									/* DTCベクタ・テーブル(0x100バイトでアライメント済み) */

/*
 * DTC
 * 初期化
 */
void dtc_init(void)
{
	u2  dtc_buffer_near;
	u2  dtc_buffer_add;
	u2  dtc_offset;
	u1* log_buf;
	u2  log_bytes;

	/* 周辺イネーブル・レジスタ1でDTCを有効にする */
	PER1 |= RL78F_PER1_DTCEN;

	/* DTCベクタの先頭アドレスを得る(0x100バイト単位にアライメント) */
	dtc_buffer_near = (u2)&dtc_buffer[0];
	dtc_buffer_add = (u2)((dtc_buffer_near + 0x00ff) & 0xff00);

	/* 算出したDTCベクタとバッファとのオフセットを算出 */
	dtc_offset = (u2)(dtc_buffer_add - dtc_buffer_near);

	/* DTCベクタを設定 */
	dtc_vector = &dtc_buffer[dtc_offset];

	/* ログバッファを設定 */
	log_buf = &dtc_buffer[dtc_offset + DTC_BUFFER_SIZE];

	/* ログバッファで使用可能なバイト数を決定 */
	log_bytes = sizeof(dtc_buffer) - (dtc_offset + DTC_BUFFER_SIZE);

	/* ログへ通知 */
	log_set_buf(log_buf, log_bytes);

	/* DTC起動要因をすべて禁止 */
	DTCEN0 = RL78F_DTCEN_DISABLE;
	DTCEN1 = RL78F_DTCEN_DISABLE;
	DTCEN2 = RL78F_DTCEN_DISABLE;
	DTCEN3 = RL78F_DTCEN_DISABLE;
	DTCEN4 = RL78F_DTCEN_DISABLE;
#ifdef R5F10PPJ
	DTCEN5 = RL78F_DTCEN_DISABLE;
#endif /* R5F10PPJ */

	/* DTCベースレジスタを設定 */
	DTCBAR = (u1)(dtc_buffer_add >> 8);

	/* コントロール・データ0の起動要因をUART0送信完了に割り当てる */
	dtc_vector[DTC_UART0_TX] = DTC_CTRL0_OFFSET;

	/* コントロール・データ0の設定(送信時に設定する部分はスキップ) */
	dtc_vector[DTC_CTRL0_OFFSET + DTC_DTCCR_OFFSET] = RL78F_DTCCR_SAMOD;
	dtc_vector[DTC_CTRL0_OFFSET + DTC_DTBLS_OFFSET] = RL78F_DTBLS_ONE;
	dtc_vector[DTC_CTRL0_OFFSET + DTC_DTRLD_OFFSET] = RL78F_DTRLD_ONE;
	dtc_vector[DTC_CTRL0_OFFSET + DTC_DTDARL_OFFSET] = (u1)(RL78F_DTDAR_SDR00L & 0x00ff);
	dtc_vector[DTC_CTRL0_OFFSET + DTC_DTDARH_OFFSET] = (u1)(RL78F_DTDAR_SDR00L >> 8);

	/* コントロール・データ1の起動要因をUART1送信完了に割り当てる */
	dtc_vector[DTC_UART1_TX] = DTC_CTRL1_OFFSET;

	/* コントロール・データ1の設定(送信時に設定する部分はスキップ) */
	dtc_vector[DTC_CTRL1_OFFSET + DTC_DTCCR_OFFSET] = RL78F_DTCCR_SAMOD;
	dtc_vector[DTC_CTRL1_OFFSET + DTC_DTBLS_OFFSET] = RL78F_DTBLS_ONE;
	dtc_vector[DTC_CTRL1_OFFSET + DTC_DTRLD_OFFSET] = RL78F_DTRLD_ONE;
	dtc_vector[DTC_CTRL1_OFFSET + DTC_DTDARL_OFFSET] = (u1)(RL78F_DTDAR_SDR10L & 0x00ff);
	dtc_vector[DTC_CTRL1_OFFSET + DTC_DTDARH_OFFSET] = (u1)(RL78F_DTDAR_SDR10L >> 8);

	/* 高速DTCチャネル0を割り当てるベクタへ、ダミーデータを設定する */
	dtc_vector[DTC_UART0_RX] = DTC_CTRL0_OFFSET;

	/* 高速DTCチャネル0の設定(受信時に設定する部分はスキップ) */
	SELHS0 = DTC_UART0_RX;
	HDTCCR0 = RL78F_DTCCR_DAMOD;
	HDTSAR0 = (u2)(RL78F_DTDAR_SDR01L & 0x0fff);
	HDTRLD0 = RL78F_DTRLD_ONE;

	/* 高速DTCチャネル1を割り当てるベクタへ、ダミーデータを設定する */
	dtc_vector[DTC_UART1_RX] = DTC_CTRL1_OFFSET;

	/* 高速DTCチャネル1の設定(受信時に設定する部分はスキップ) */
	SELHS1 = DTC_UART1_RX;
	HDTCCR1 = RL78F_DTCCR_DAMOD;
	HDTSAR1 = (u2)((u2)(&SDR11L) & 0x0fff);
	HDTRLD1 = RL78F_DTRLD_ONE;
}

/*
 * DTC
 * UART送信READYチェック
 *
 * ※READYであればU1_TRUEを返す
 */
u1 dtc_tx_is_ready(u1 ch)
{
	u1 ret;

	/* 戻り値をREADYで初期化 */
	ret = U1_FALSE;

	/* チャネル判定 */
	if (0 == ch)
	{
		if (0 == (u1)(DTCEN1 & RL78F_DTCEN1_UART0_TX))
		{
			/* UART0レディ */
			ret = U1_TRUE;
		}
	}
	else
	{
		if (0 == (u1)(DTCEN1 & RL78F_DTCEN1_UART1_TX))
		{
			/* UART1レディ */
			ret = U1_TRUE;
		}
	}

	return ret;
}

/*
 * DTC
 * 転送開始
 *
 * http://documentation.renesas.com/doc/products/mpumcu/tu/tnr8ca047aj.pdf
 * 3-2節を参照。DTCEN1にORした値とは別の要因が再起動されることを防ぐ
 *
 * ※割り込み禁止状態で呼ばれる
 */
static void dtc_enable(u1 en)
{
	u1 dtcen;
	u1 dtcct;
	u1 retry;

	/* dtcenを初期化 */
	dtcen = (u1)(DTCEN1 | en);

	/* リトライあり */
	retry = U1_TRUE;

	/* 無限ループ */
	while (U1_TRUE == retry)
	{
		/* DTCEN1をセット */
		DTCEN1 = dtcen;

		/* リトライなし */
		retry = U1_FALSE;
	
		/* UART0受信完了 */
		if (0 != (u1)(DTCEN1 & RL78F_DTCEN1_UART0_RX))
		{
			/* DTCCT取得 */
			dtcct = HDTCCT0;

			/* 0x00,0x80-0xffの範囲であればタイミング競合している */
			if ((dtcct < 0x01) || (dtcct > 0x7f))
			{
				dtcen &= (u1)(~RL78F_DTCEN1_UART0_RX);
				retry = U1_TRUE;
			}
		}

		/* UART0送信完了 */
		if (0 != (u1)(DTCEN1 & RL78F_DTCEN1_UART0_TX))
		{
			/* DTCCT取得 */
			dtcct = dtc_vector[DTC_CTRL0_OFFSET + DTC_DTCCT_OFFSET];

			/* 0x00,0x80-0xffの範囲であればタイミング競合している */
			if ((dtcct < 0x01) || (dtcct > 0x7f))
			{
				dtcen &= (u1)(~RL78F_DTCEN1_UART0_TX);
				retry = U1_TRUE;
			}
		}

		/* UART1受信完了 */
		if (0 != (u1)(DTCEN1 & RL78F_DTCEN1_UART1_RX))
		{
			/* DTCCT取得 */
			dtcct = HDTCCT1;

			/* 0x00,0x80-0xffの範囲であればタイミング競合している */
			if ((dtcct < 0x01) || (dtcct > 0x7f))
			{
				dtcen &= (u1)(~RL78F_DTCEN1_UART1_RX);
				retry = U1_TRUE;
			}
		}

		/* UART1送信完了 */
		if (0 != (u1)(DTCEN1 & RL78F_DTCEN1_UART1_TX))
		{
			/* DTCCT取得 */
			dtcct = dtc_vector[DTC_CTRL1_OFFSET + DTC_DTCCT_OFFSET];

			/* 0x00,0x80-0xffの範囲であればタイミング競合している */
			if ((dtcct < 0x01) || (dtcct > 0x7f))
			{
				dtcen &= (u1)(~RL78F_DTCEN1_UART1_TX);
				retry = U1_TRUE;
			}
		}
	}
}

/*
 * DTC
 * UART送信開始
 *
 * ※割り込み禁止状態で呼ばれる
 */
void dtc_tx_start(u1 ch, u1* buf, u1 len)
{
	u2 buf_near;

	/* バッファアドレスの下位16bitのみ取得する(RAMまたはROMミラーへの配置が前提) */
	buf_near = (u2)&buf[0];

	/* チャネル判定 */
	if (0 == ch)
	{
		/* 転送元アドレス */
		dtc_vector[DTC_CTRL0_OFFSET + DTC_DTSARL_OFFSET] = (u1)(buf_near);
		dtc_vector[DTC_CTRL0_OFFSET + DTC_DTSARH_OFFSET] = (u1)(buf_near >> 8);

		/* 転送回数 */
		dtc_vector[DTC_CTRL0_OFFSET + DTC_DTCCT_OFFSET] = len;

		/* 転送開始 */
		dtc_enable(RL78F_DTCEN1_UART0_TX);
	}
	else
	{
		/* 転送元アドレス */
		dtc_vector[DTC_CTRL1_OFFSET + DTC_DTSARL_OFFSET] = (u1)(buf_near);
		dtc_vector[DTC_CTRL1_OFFSET + DTC_DTSARH_OFFSET] = (u1)(buf_near >> 8);

		/* 転送回数 */
		dtc_vector[DTC_CTRL1_OFFSET + DTC_DTCCT_OFFSET] = len;

		/* 転送開始 */
		dtc_enable(RL78F_DTCEN1_UART1_TX);
	}
}

/*
 * DTC
 * UART受信開始
 *
 * ※割り込み禁止状態で呼ばれる
 */
void dtc_rx_start(u1 ch, u1* buf, u1 len)
{
	u2 buf_near;

	/* バッファアドレスの下位16bitのみ取得する(RAMまたはROMミラーへの配置が前提) */
	buf_near = (u2)&buf[0];

	/* チャネル判定 */
	if (0 == ch)
	{
		/* 転送先アドレス */
		HDTDAR0 = buf_near;

		/* 転送回数 */
		HDTCCT0 = len;

		/* 転送開始 */
		dtc_enable(RL78F_DTCEN1_UART0_RX);
	}
	else
	{
		/* 転送先アドレス */
		HDTDAR1 = buf_near;

		/* 転送回数 */
		HDTCCT1 = len;

		/* 転送開始 */
		dtc_enable(RL78F_DTCEN1_UART1_RX);
	}
}

/*
 * DTC
 * UART転送回数取得
 */
 void dtc_rx_get_dtcct(u1 ch, u1* dtcct)
{
	/* チャネル判定 */
	if (0 == ch)
	{
		*dtcct = HDTCCT0;
	}
	else
	{
		*dtcct = HDTCCT1;
	}
}