RL78/F14マイコンを使用したCAN通信/LIN通信のチェッカー
Rev. | 85fcb496057f40f6bb6a30b02de357ea2efb6483 |
---|---|
Tamaño | 10,554 octetos |
Tiempo | 2016-07-17 11:16:45 |
Autor | Yasushi Tanaka |
Log Message | 新規作成(ターゲットボード:ルネサスQB-R5F10PPJ-TB、CC-RL用)
|
/*
* 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;
}
}