RH850F1KHで自動生成コードをベースでCANドライバーを作る2

前記事では北斗電子さんHSBRH850F1KH176をターゲットにRH850自動コード生成をベースとし、RH850/U2A 用のCANドライバサンプルコードを、RH850F1KH用に基本部分を移植しました。次にCAN送信をテストしていきます。今回は企画元がFD未対応なので、CAN2.0のみの使用です。


CAN受信側のハードは、PEAK CAN-USB FDバージョン を用います。代理店さんから購入予定でしたが、ebayで新品放出品があり入手しました。正規ルート以外はコピー品も多いようなので要注意です。ドイツから直接購入は出来ないようです。過去職場でCAN2.0版を導入しましたが、筐体が黒になり安っぽさが消えたように見えます。Kavaer PCeボートも保有していますが、今回、新しく試しています。

配線はpin1とpin4を逆にしないよう注意です。HSBRH850F1KH176 のCANコネクタはpin番号がシルクに書いないようです。JST製なのでpin番がハウジングに書いてあったと思いましたが見当たらず。付属のケーブルは線が細くはんだ付して直ぐ切れそうリスキーです。太い線で作り直した方がよさげです。CANも絶縁になっていないので回路検討としてはCANトランシーバから先は別で組んだ方が良いかも。

CAN受信側のソフトはオープンソースのBUSMATER を用います。CAN DBを定義でき、CANシグナルに分けてサンプリングとログができます。CANLayzer の CAN DB のコンバートも可。しかし数年間、UPDATEがありません。のでCAN-FDには未対応です。過去職場でも紹介し導入し、割と評判が良かったですが、世間的には知名度が低いのでしょうか? (リリース当時ETASさんもアピールしていましたが) にしてもKavaer CAN King ( 全然Kingじゃない )は使い物にならないと思うのですが…


マニュアル 「表 24.125 通信速度の設定例」の表内の「(数値)」が、CANクロックの分周ですが、そのまま設定するとBUSエラーになります。通信速度の計算式をみると、そこから -1 が必要です。CANクロック:fCAN40MHz1Mbpsの場合、r_rh850_can_cfg.c の設定は以下のようになります。Tq数( 1bitの分解能、通信相手によっては調整要す )は取急ぎ粗目に 8 としています。

const can_ch_cfg_t  g_can_ch_cfg[ USED_UNIT_NUM ][ MAX_CH_NUM_U0 ] = {
// ========================== U n i t 0 設 定 ==========================
{
	// ------------------------ C h 0 設 定 ---------------------------
    {
    ・・・中略・・・
     /* ---- Normal Baudrate ----
       パラメータ( 分周比, SEG1 Bit-Timing, SEG2 Bit-Timing, Jump幅)
  	 */
    	CAN_CFG_N_BAUDRATE(
			// 1Mbps 分周比 = 40Mhz ÷ ( 1MHz × Tq数:8 ) = 5 より-1
   			4U, CAN_NTSEG1_5TQ, CAN_NTSEG2_2TQ, CAN_NSJW_1TQ
		),
    	/* ---- Data Baudrate ---- */
    	CAN_CFG_D_BAUDRATE(
			// 1Mbps 分周比 = 40Mhz ÷ ( 1MHz × Tq数:8 ) = 5 より-1
			// 取急ぎCAN2.0では Normal Baudrate と同じでよい模様。
   			4U, CAN_NTSEG1_5TQ, CAN_NTSEG2_2TQ, CAN_NSJW_1TQ
		),

設定値まとめを以下に示します。なお一般的に乗用車両は500kbps、働く車やレクレーションVehicleは250kbpsですが、レースや車両評価で使う場合は1Mbpsが多いようです。

項目
通信速度1Mbps
fCAN クロック40Mz
クロック分周5
Tq数8
SEG1 Bit Timing5
SEG2 Bit Timing2
Bitズ レジャンプ幅1

CANクロック::fCANは、設定にもよりますが下図の部分でよいようです。


RH850では送信は3つの方法があります。その中で送信Buffer が一番シンプルな手段です。使用する APIは R_CAN_TransmitByTxBuf (orgは略しすぎなので改名してます) です。送信Buffer 数は以下のようになっています。

項目
1 Channelあたり送信Buffer数32
1 Unitあたり送信Buffer SFR数255

CAN Channel と 送信Buffer の割当てがイマイチ分かりにくいです。単純に 「 Channel番号 × 36 + CH毎に使うBuffer番号」 でいいようです。OrignalのAPIは 送信Buffer 番号は絶対値なので、ch毎の相対にした方が使いやすいでしよう。以下コードを追加しました。

#define CAN_CH_TO_TX_BUF( ch, num )			( ch * MAX_TX_BUF_OF_CH	+ num )
・・・中略・・・
	// 送信Buffer番号を算出
	txbuf_idx = CAN_CH_TO_TX_BUF( ch_idx, txbuf_idx )

以下呼出しコード例です。基板確認のため、Ch 0、Ch 1両方試します。

	Can_RtnType ret;
	can_frame_t	frame;

	frame.ID	= 0x700;
	frame.DLC	= 8;
	frame.IDE	= 0;	  // 標準frame
	frame.TMFDF = 0;	// CAN2.0
	frame.RTR	= 0;
	frame.DB[ 0 ]	= 0x30;
	frame.DB[ 1 ]	= 0x31;
	frame.DB[ 2 ]	= 0x32;
	frame.DB[ 3 ]	= 0x33;
	frame.DB[ 4 ]	= 0x34;
	frame.DB[ 5 ]	= 0x35;
	frame.DB[ 6 ]	= 0x36;
	frame.DB[ 7 ]	= 0x37;

	ret =  R_CAN_TransmitByTxBuf(	0,	// i : CAN Unit
								  0, 	    // i : CAN Ch番号
									0, 	    // i : 送信Bfffer番号
									&frame	// i : CAN Frame
	);
	
  frame.ID	= 0x701;
	frame.DLC	= 8;
	frame.IDE	= 0;	// 標準frame
	frame.TMFDF = 0;	// CAN2.0
	frame.RTR	= 0;
	frame.DB[ 0 ]	= 0x40;
	frame.DB[ 1 ]	= 0x41;
	frame.DB[ 2 ]	= 0x42;
	frame.DB[ 3 ]	= 0x43;
	frame.DB[ 4 ]	= 0x44;
	frame.DB[ 5 ]	= 0x45;
	frame.DB[ 6 ]	= 0x46;
	frame.DB[ 7 ]	= 0x47;

	ret =  R_CAN_TransmitByTxBuf(	0,	// i : CAN Unit
								 	1, 	    // i : CAN Ch番号
									0, 	    // i : 送信Bfffer番号
									&frame	// i : CAN Frame
	);

BUSMASTERでの受信結果は以下のとおりです。送信できない場合、あまり不確定要素はないため、配線ミスかBaudrate間違いの可能性が高いです。

なお送信前に、送信中かエラー中かの判定もないので追加したほうがいいでしょう。API: R_CAN_CheckTxBufResult でも代用できるかもしれません。

	{
		volatile uint32_t sts;

		sts = RCFDCnCFDCmSTS( ch_idx );
		if ( ( sts & CAN_COM_STS_BIT_ON ) == 0) {   // Ch通信可=不可
			return CAN_RTN_TX_ERROR ;
		}

		if ( ( sts & CAN_BUSOFF_STS_BIT_ON ) != 0) {  // Ch BUS-OFF
			return CAN_RTN_TX_ERROR ;
		}

		if ( ( sts & CAN_TRM_STS_BIT_ON ) != 0) {  	// Ch送信STATUS=送信中
			return CAN_RTN_TX_ERROR ;
		}
	}


送信完了割込みは、エラー割込みや送信前のSFRチェックを行えば特に不要です。割込が多発すると、組込みでは貴重な処理能力を食います。今のところは余裕があるため検出しておきました。弊方での実装例は以下のとおりです。実装先は自動コード生成された r_smc_intprg. c です。

/* CAN0 TRANSMIT INTERRUPT */
#if defined (__CCRH__)
#pragma interrupt IntCAN0Tx(enable=false, channel=26, fpu=true, callt=false)
#elif defined (__ghs__)
#pragma ghs interrupt
#elif defined (__ICCRH850__)
#pragma type_attribute=__interrupt
#else
#error Unknown Compiler
#endif
void IntCAN0Tx(void)
{
/* Start user code for IntCAN0Tx. Do not edit comment generated here */
	R_CAN_DispatchEevent( 0 /*unit*/, 0 /* ch.*/, CAN_EVENT_SEND_COMPLATE );
/* End user code. Do not edit comment generated here */
}

弊方では上記の R_CAN_DispatchEevent の中で、登録ずみcallbackを呼んでいます。例がなくとも想像がつくでしょう。r_rh850_can_cfg.c の設定も少し変更します。以下の 0xFFFFU の部分、送信Buffer の32個に対して1bitづつ有効無効を指定します。取急ぎ全部有効にしておきます。

const can_ch_cfg_t  g_can_ch_cfg[ USED_UNIT_NUM ][ MAX_CH_NUM_U0 ] = {
// ========================== U n i t 0 設 定 ==========================
{
	// ------------------------ C h 0 設 定 ---------------------------
    {
 ・・・中略・・・   
        /* ---- Tx/Rx FIFO buffer ---- */
        0x00000000UL,
     	  0x00000000UL,
        0x00000000UL,
        /* ---- Tx queue ---- */
        0x00000000UL,
        /* ---- 送信Buffer割込許可 RCFDCnCFDTMIECm ---- */
        0xFFFFU		// LSBより 1bit 1Buffer で割当て
    }

割込みが発生しない、割込みが発生後、RESETする場合は、割込み設定が正しくできていない可能性が高いです。前記事をよく確認します。

以上で送信まで試せました。受信編へ続きます。


SFRは多すぎてウオッチするのに時間がかかります。CS+ にもあるかもしりませんが、e2Studioでとても役に立った機能を記録しておきます。

① 選択されたレジスターを使うと、確認したいSFR値だけをまとめておける。

② 上記①の抽出のため、SFR一覧の目視検索に時間がかがる。SFRiodefine.hの定義名なので、マニュアル記載名が検索キーにならないところ、アドレスでも検索できる。

RH850F1KHで自動生成コードをベースでCANドライバーを作る1

前記事では、北斗電子さんHSBRH850F1KH176をターゲットにRH850自動コード生成を行いました。しかしCANドライバは自動コード生成の対象になっていません。そこで自動コード生成とHSBRH850F1KH176 に合わせたCANドライバプログラムを用意することにしました。その覚え書きです。


CANドライバ部は、RH850は設定項目も多く、RH850のCAN機能のアプリケーションノートも無いようです。一からは大変そうなのでサンプルコードを探します。現在、ルネサスから提供されているのは、RH850/U2A 用だけでした。同サンプルコードは、製品コンパイラやマイコン購入者でなくても、ルネサスアカウントを持っていればダウンロードできました。

取り急ぎ RH850F1KHの設定でbuildしてみると、ほぼほぼ通ってしまいます。それはRH850/U2A 専用にSFRを定義が作成しれていて、RH850F1KHiodefine.h は参照していないからです。SFRアドレスもCAN構成も大分違います。RH850F1KH用に移植が必要です。


RH850 CAN機能はこりまでと異なる用語等があります。実用ベースでの見たところ以下のように理解しました。

用語・機能解釈
グローバルCAN「グローバル=世界」 ではないです。RH850のみでのCAN2.0、CAN-FD、複数のCAN UNITを管理するための機構です。
クラシカルCANCAN2.0B のこと。
CAN UNIT所謂CAN コントローラ、この配下に複数のCANチャンネルが連なります。
SFR添え字UINT番号、CH番号等の略記号。マニュアルの表 24.9 添字 に説明あり。
受信ルール従来のCAN Message Box のCAN IDマスクと同意。
送信Buffer従来のCAN Message Box の送信専用版。
受信Buffer従来のCAN Message Box の受信専用版。
データBit Rate少なくとも CAN2.0B では通常Bit Rateと同じ。
FIFO Buffer従来のCAN Message Boxとは別の先入れ先出し方式のMessage Boxの模様。未だ動作未確認です。
割り込みベクタ方式一般的な「テーブル参照方式」と、「優先度に基づいた直接分岐方式」があります。

U2A用サンプルコードのSFR定義: r_rh850_can_sfr.h を変更していきます。ルネサスのマニュアルには、UNIT番号、Channel番号、Buffer番号などぱ可変要素としてSFR名が記載されています。例えば、RCFDCnCFDCmDCFGnはUNIT、mはChannelを示します。実名は RCFDC0CFDC0~7DCFG、iodefine.h はでは RCFDC0.CFDC0~7DCFG となります。よってマニュアルに合わせたSFR名でコードを書いた方が検索性に優れます。 U2A用サンプルコードはそのようになっていますがF1KHと命名が違うため合わせていきます。

  • RSCFDnXXX は、 RCFDCnXXX に一括置換。

これでマニュアルとSFRの対比がつかめるようになります。

U2A用サンプルコードのSFR定義: r_rh850_can_sfr.h では、SFRアドレスは CAN UNIT 毎のベースアドレスからの計算式になっています。そこでまず r_rh850_can_cfg.h にて CAN UNIT のベースアドレスを変更します。U2A用は CAN UNIT は一つと決め打ちです。F1KHの最多pin種では2つのため、ベースアドレスはグローバル変数とし逐次切替式としました。

uint32_t	CAN_START_ADDR;
#define R_CAN_SelectUnit( ch ) 	( CAN_START_ADDR = CAN_START_ADDR [ ch ] )
const uint32_t  CAN_UINT_ADDR[2] = { 0xFFD00000UL /* UNIT 0 */, 0xFFD20000UL /* UNIT 1 */};

あとは SFR名 で マニュアルを検索し、アドレスを変更していきます。アドレスはGlobal系の数個以外は全部違います。50個近くあるので大変です。ついでに日本語名もコメント付与します。計算式のオフセットやCH毎増分など違う場合もあるので修正します。以下 r_rh850_can_cfg.hの一例です。

#define RCFDCnCFDTMCp(p) CAN_REG8 (0x0250 + (p)) // 送信バッファ制御(p)
・・・中略・・・
#define RCFDCnCFDCFCCk(k) CAN_REG32(0x0118 + (0x04 * (k))) // 送受信FIFOバッファ構成/制御(k)
#define RCFDCnCFDCFSTSk(k) CAN_REG32(0x0178 + (0x04 * (k)))	// 送受信FIFOバッファステース(x)

U2AにしかないSFRの削除、F1KHしかないSFRの追加をします。こちらはマニュアルと照らし合わせていくしかありません。手間がかかります。以下 r_rh850_can_sfr.h の一例です。

#define RCFDCnCFDGTINTSTS0  CAN_REG32(0x0610)	// Global TX割り込みステータス0 
#define RCFDCnCFDGTINTSTS1  CAN_REG32(0x0614)	// Global TX割り込みステータス1 ☆
#define RCFDCnCFDGFDCFG     CAN_REG32(0x0624)		// Global FDコンフィグレーション ☆

U2AF1KHで、同じSFRでBit構成が異なるのものがあります。こちらはマニュアルと照らしあわせていくしかありません。弊方ではコメントを付与ついでに調べていきます。幸い数はすくないです。決定的に変更しないとまずいのはBaudrate( RCFDCnCFDCmNCFG, RCFDCnCFDCmDCFG )ですまさかと思い弊方では直ぐに気付けませんでした。トラップです。以下 r_rh850_can_sfr.h の一例です。

#define CAN_DTSEG2_BIT_POS              20U	// Data BitRate Timeセグメント2 (3bit)
#define CAN_DTSEG1_BIT_POS              16U	// Data BitRate Timeセグメント1 (4bit)

U2A用では、CAN構成は r_rh850_can_cfg.[ch] に記述されています。F1KHに構成が異なるため変更が必要です。弊方では CAN UNIT 毎に定義できるようにしています。

#define MAX_CH_NUM_U0					8
#define MAX_CH_NUM_U1					4	// 324pinの場合のみ
#define MAX_CH_NUM(unit)      ( unit == 0 ? MAX_CH_NUM_U0 : MAX_CH_NUM_U1 )
#define USED_UNIT_NUM         1	// 324pinは2
#define MAX_TX_BUF_OF_CH			32	// CH毎の送信Buffer数

送信バッファ数はF1KHが多いので追加します。こちらは r_rh850_can_drv.h。

#define CAN_TXBUF16         16U
#define CAN_TXBUF17         17U
・・・中略・・・
#define CAN_TXBUF31         31U
#define CAN_MAX_TXBUF_NUM   32U

ドライバプログラムで取り扱う構造体もF1KHでは少し違います。CAN Frame と CAN Channel 定義 を修正します。以下CAN Frameの例です。

typedef struct {
・・・中略・・・
	uint32_t TS :16;   /* 受信時刻                           */
	uint32_t RESERVE:12;  /* 空き                            */
	uint32_t DLC :4;	/* DLC(データ部長)                   */
	uint32_t TMESI:1;	/* CAN-FD 0:ERRアクティブNode 1:ERRパッシブNode */
	uint32_t TMBRS:1;	/* CAN-FD DATA領域Bitrate 0:変わらない 1:変わる */
	uint32_t TMFDF:1;	/* CAN-FD 0:CAN2.0 1:CAN-FD */
	uint32_t RESERVE2:13;	/* FD Status(TMESI,TMESI           */
	uint32_t LBL:16;	/* 受信バッファラベル                  */
・・・中略・・・
} can_frame_t;


自動コード生成部を使う部分、セルフテスト部は特に不要です。以下.c は、Build対象外にします。

  • r_rh850_can_int.c
  • r_rh850_can_io.c
  • r_rh850_can_drv2.c

r_rh850_can_drv.c が CANドライバAPI 部です。コメントは少な目で英語なので、内容を確認しながらコメントを追記していきます。全APIで行うとタイヘンなので取り急ぎ使いそうなもののみです。併せてCAN UNIT番号を指定可能にしておきます。以下一部例です。

/******************************************************************************
 * Function Name: R_Can_Init
 * Description  : CAN UNIT毎に初期化を行う。
 *                - CAN用RAMクリア
 *                - Gobal STOPモード解除を待つ。
 *                - CAN2.0 と FD切替え
 *                - ch毎のBaudrate設定
 *                - 受信Ruleの設定
 *                - 受信Bufferの設定
 *                各設定は、r_rh850_can_cfg.c で行う。
・・・中略・・・
 *	              CAN_RTN_ARG_ERROR -
 *	                  パラメータエラー
 ******************************************************************************/
Can_RtnType R_CAN_Init(
	const uint8_t unitNum,	// i : CAN Unit
	const uint8_t chNum,		// i : 使用CAN ch数
	const BOOL useCanFd		  // i : CAN FD使用
) {

修正内容の整合性があっているか、仮Buildします。自己あやまり以外で引っかかる部分が少しあります。RCFDCnCFDTMIECm のポインタ型はU2A用では16bitでしたがF1KHでは32bitにする必要があります。

・・・中略・・・
volatile uint32_t *p_TMIEC;
・・・中略・・・

オリジナルのままでは使いにくそうなので多少機能追加しています。 Callback 機構とそのための割込みに仕込む EVEVT Dispacher です。

/******************************************************************************
 * Function Name: R_CAN_DispatchEevent
 * Description  : CAN ENEVTを処理する
 *                割込ハンドラから呼ばれます
 *                割込ペリフェラルとのI/F部です。
 * Remark:
 * - 現在は、送信Bufferによる送信のみサポート。
 * - RH850では、受信Bufferの割込みはない。
 ******************************************************************************/
void R_CAN_DispatchEevent(
	const uint8_t		unitNum, // i : CAN Unit
	can_ch_t			  ch_idx,	 // i : CAN Ch番号
	const uint8_t		event		 // i : ENEVT No.
) {
・・・中略・・・
/******************************************************************************
 * Function Name: R_CAN_SetRecvCallback
 * Description  : CAN受信Callbckを設定する。
 ******************************************************************************/
void R_CAN_SetRecvCallback(
	const uint8_t		  unitNum,	// i : CAN Unit
	can_ch_t			    ch_idx,		// i : CAN Ch番号
	CAN_RECV_CALLBAK	func		  // i : 受信Callbak
) {
・・・中略・・・
/******************************************************************************
 * Function Name: R_CAN_SetSendCallback
 * Description  : CAN送信Callbckを設定する。
 ******************************************************************************/
void R_CAN_SetSendCallback(
	const uint8_t		 unitNum,	// i : CAN Unit
	can_ch_t			    ch_idx,	// i : CAN Ch番号
	CAN_SEND_CALLBAK	func		// i : 受信Callbak
) {
・・・中略・・・
/******************************************************************************
 * Function Name: R_CAN_SetErrCallback
 * Description  : CANエラーCallbckを設定する。
 ******************************************************************************/
void R_CAN_SetErrCallback(
	const uint8_t		unitNum,	// i : CAN Unit
	can_ch_t			  ch_idx,		// i : CAN Ch番号
	CAN_ERR_CALLBAK	func		  // i : 受信Callbak
) {


自動コード生成でのmainモジュール: r_cg_main.c の実装は以下のような感じです。

・・・中略・・・
/* Start user code for include. Do not edit comment generated here */
#include "r_rh850_can_sfr.h"
#include "r_rh850_can_drv.h"
/* End user code. Do not edit comment generated here */
・・・中略・・・

void main(void)
{
・・・中略・・・
    r_main_userinit();
    r_main_startCan();

    while ( 1U ) {
・・・中略・・・
}

void r_main_startCan(void)
{
	// CAN Controller 初期化
	if ( R_CAN_Init( 0/*UNIT*/, 2/*CH数*/, FALSE/*CANFD*/ ) != CAN_RTN_OK ) {
		return;
	}

	// Ch0 Callbak設定 
	R_CAN_SetErrCallback ( 0/*UNIT*/, 0/*ch.*/, r_main_errCan0  );
	R_CAN_SetRecvCallback( 0/*UNIT*/, 0/*ch.*/, r_main_recvCan0 );
	R_CAN_SetSendCallback( 0/*UNIT*/, 0/*ch.*/, r_main_sendCan0 );

	// Ch1 Callbak設定
	R_CAN_SetErrCallback ( 0/*UNIT*/, 1/*ch.*/, r_main_errCan1  );
	R_CAN_SetRecvCallback( 0/*UNIT*/, 1/*ch.*/, r_main_recvCan1 );
	R_CAN_SetSendCallback( 0/*UNIT*/, 1/*ch.*/, r_main_sendCan1 );

	// Global CAN開始
	if ( R_CAN_GlobalStart( 0/*UNIT*/ ) != CAN_RTN_OK ) {
		return;
	}

	// CAN 0ch 開始
	if ( R_CAN_ChStart( 0/*UNIT*/, 0 /* Ch. */ ) != CAN_RTN_OK ) {
		return;
	}

	// CAN 1ch 開始
	if ( R_CAN_ChStart( 0/*UNIT*/, 1 /* Ch. */ ) != CAN_RTN_OK ) {
		return;
	}

CAN機能と割込は場合、HSBRH850F1KH176 の回路実装から各種割当ては以下のようになります。なお受信Buffer による受信割込みはRH850は無いです。送受信FIFOはFIFO Buffer専用の割込みのようです。

Chanel機能ポート名ポート番号送信完割込番号送受信FIFO割込番号エラー割込番号
0受信CAN0RXP10_02524
0送信CAN0TXP10_1262524
1受信CAN1RXP0_2114113
1送信CAN1TXP0_3115114113

CANペリフェラルの定義は、e2stdioの自動生成で以下のように行います。

上記の設定で、対応するポートの入出力の設定はされるので、以下2つの個別の設定はしないです。

CANペリフェラルの定義は、Pin.cR_Pins_Create に生成されます。しかし生成されるだけで、 Config_PORT.c などからcallされていません。呼出しコードは自分で書く必要がありました。弊方では直ぐ気付けずトラップでした。弊方では、Config_PORT_user.c から以下のように呼出追加しました。

void R_Config_PORT_Create_UserInit(void)
{
    /* Start user code for user init. Do not edit comment generated here */
	  R_Pins_Create();
    /* End user code. Do not edit comment generated here */
}

割込みの設定は一旦以下ようにします。これでハンドラのベクタテーブルへの定義とスケルトン、割込み有効無効のAPIが生成されます。

しかしCAN割込みの場合、割込み優先度割り込みベクタ方式 の設定コードは自動生成されませんでした。タイマ等では自動生成されるので、ここはトラップです。デフォルトは割込み優先度です。そのまま動かすと優先度15割込み未定義で無限loopしました。boot.asmを見ると自動生成デフォルト状態では _Dummy_EI で無限loopになってます。この方式は使わない方が無難なようです。

割込み設定に関するコード例は以下のとおりです。r_main_startCan() の各Ch.初期化後に追記しましたた。

	/* CH0 割込み方式とLEVEL設定 */
    INTC1.ICRCAN0ERR.BIT.TBRCAN0ERR = _INT_TABLE_VECTOR;
    INTC1.ICRCAN0REC.BIT.TBRCAN0REC = _INT_TABLE_VECTOR;
    INTC1.ICRCAN0TRX.BIT.TBRCAN0TRX = _INT_TABLE_VECTOR;
    INTC1.ICRCAN0ERR.UINT16 &= _INT_PRIORITY_LEVEL4;
    INTC1.ICRCAN0REC.UINT16 &= _INT_PRIORITY_LEVEL4;
    INTC1.ICRCAN0TRX.UINT16 &= _INT_PRIORITY_LEVEL4;

	/* CH1 割込み方式とLEVEL設定 */
    INTC2.ICRCAN1ERR.BIT.TBRCAN1ERR = _INT_TABLE_VECTOR;
    INTC2.ICRCAN1REC.BIT.TBRCAN1REC = _INT_TABLE_VECTOR;
    INTC2.ICRCAN1TRX.BIT.TBRCAN1TRX = _INT_TABLE_VECTOR;
    INTC2.ICRCAN1ERR.UINT16 &= _INT_PRIORITY_LEVEL4;
    INTC2.ICRCAN1REC.UINT16 &= _INT_PRIORITY_LEVEL4;
    INTC2.ICRCAN1TRX.UINT16 &= _INT_PRIORITY_LEVEL4;

    // CH0 割込み有効化
	IntCAN0Error_enable_interrupt( );
	IntCAN0TxRxFIFORxCmp_enable_interrupt( );
 	IntCAN0Tx_enable_interrupt( );

    // CH1 割込み有効化
	IntCAN1Error_enable_interrupt( );
	IntCAN1TxRxFIFORxCmp_enable_interrupt( );
 	IntCAN1Tx_enable_interrupt( );


以上おおざっぱなところ、初期化は通過し、送受信スタンパイまで行き着きました。しかし試行錯誤や細かい部分でハードルもあり、ここまで延べて2weekくらいは要したかと思います。

送信編につづきます。

Xperia E1 Dual D2105 をAndroid 6または7.1.2相当にSetupする1

音楽再生専用にほどよい4inchディスプレイのXperia E1。Walkmanボタンで画面さわらずとも再生とポーズができます。FMラジオ、大型スピーカ、SIMスロット2。自動車整備中でイヤフォンが使えないとき、ツナギのぽっけに入れて音楽再生にちょうど良いです。

標準OSはAndroid4.1.2。色々なOSが出ています。Walkmanボタンが使えるカスタムOSを模索中です。試したOSと結果のメモです。


①Bootloader unlock 解除コードの入手 → ②Bootloader unlock → ③customリカバリ書込み → ④OS 書込みと他の基本手順はXperiaと同様です。 ③の内容が少し違いました。recovery領域にcustomリカバリ書込みはエラーとなり、boot領域に書込むと上手く起動します。

そうすると常時TWRPが起動するようになってしまいますが、OSを書くと上手くなくなってしまうので問題になかったです。なお端末のコードネームは、最初 falconss だったが途中から Shuangになったので、その両方でキーワードで情報を探す必要があるようです。


  • Andrid6相当
  • lineage14.1にくらべると動作はかなり軽い。(Open Gapp無し時)
  • Open Gappを入れても遅いが動く。Googleログインまでかなり時間要す。
  • wmaファイルは音楽再生可能。(弊方wma派につき)
  • walkmanボタンは効かない。カメラボタン扱いとなっている。
  • カメラ起動で「問題が発生しました」となる。open-camera-1-53-1.apkでも同様。
  • 吊るしラジオアプリは起動するが100Hzから変更できない。
  • ブラウザは起動するが、OS古くてgoogleサーバ側で拒否され閲覧不能。
  • インストール後、カスタムリカバリは残る。

  • Andrid7.1.2相当
  • lineage13.0にくらべると動作は重いが使えなくはない。(Open Gapp無し時)
  • Open Gappを入れるととてつもなく遅く、リセットを繰り返し起動が困難。しつこく繰返ば起動する。
  • wmaファイルは音楽再生不可。
  • walkmanボタンを押すとカメラが起動される。設定->ボタン->カメラボタンは無効にしていても起動してしまう。
  • カメラは起動動作可能。
  • 吊るしラジオアプリは起動するが、周波数表示されず何もできない。
  • ブラウザは起動し、閲覧可能。
  • インストール後、カスタムリカバリは残らない。

  • Andrid7.1.2相当
  • 初回Bootに時間かかる。
  • 大蛇の起動画面が目を引く。
  • lineage14.1にくらべると動作はやや軽い。(Open Gapp無し時)
  • Open Gappを入れると遅く、何とか起動する。Googleログインは失敗した。
  • wmaファイルは音楽再生不可。(何かの拍子に再生されてことが一度あった)
  • walkmanボタンは効かない。カメラボタン扱いとなっている。
  • カメラは起動しない
  • 吊るしラジオアプリは起動するが、周波数表示されず何もできない。E1オリジナルのラジオアプリは起動失敗する。
  • ブラウザは起動し、閲覧可能。
  • インストール後、カスタムリカバリは残らない。

  • 試さず。どのみちAndroid5なので。

  • TWRPで解凍エラーが発生し試せず。

各OSも一長一短があるようです。結果を下表にまとめます。

OS重さGapp相性walkman
ボタン
ラジオカメラWEB
閲覧
lineage-13.0××××××
lineage-14.1××××
Viper〇△×××××

本端末では、Walkmanボタン が重要です。各種バージョンを試してみました。以下その結果です。なお、wmaファイルの再生可否はOSの実験結果から、アプリ依存ではなくOS依存の模様です。

バージョンインストールWalkmanボタン
8.4.1.5 (E1オリジナル収録Ver.)××
8.4.1.4×
7.15.A.0×
8.1.A.0.5×
8.4.A.3.5××
8.5.A.3.3××

E1オリジナル 8.4.1.5はオリジナルROM: Sony_Xperia_E1_Dual_D2105_20.1.B.0.64_RU から取出しものですが解せない結果です。何か深い秘密があるのでしょうか?


冷静さをとり戻すため一旦オリジナルに戻します。VolumeDown押しながらUSBケーブルを差し、Flashモードに遷移させた後、Flashtool で Sony_Xperia_E1_Dual_D2105_20.1.B.0.64_RU を書きます。以下手順です。


以上、悔しい状況です。引き続き調査を継続します。

e2studioのProjectを、Eclipce CDT(Windows)に移行してみる

前記事では、RH850/F1KHの開発環境を用意しました。e2studioの環境をお出かけ用事務用PCにも作りたい。むろんコード作成/閲覧とC言語記述のチェック用としてです。e2studioはマシンパワーを食うし、コンパイラライセンスやバージョン互換の課題もあり、なかなかツライ。ベースは eclipce だから素のeclipceでも動くはず。そこで試してみました。

弊方では開発PCに 2019-12 CDT(C/C++ Developer Tool )を追加して使っています。IDE機能のしょぼいHIWのバックアップにも有効です。eclipceは Windows OS環境への登録的なものが無くても動くのでいつもpleiadesフォルダを移行先PCに丸コピしています。新規の方は、公式サイトからダウンロードすればよいでしょう。

e2studioのproject を移行先PCに丸コピーして、eclipce CDT のワークスペースに追加します。

これで普通にコード閲覧できるようになりました。#define値内容などホバーによる参照をするには、プロジェクト -> プロパティ -> C/C++一般 -> パスおよびシンボル からIncludeパスを追加します。

Cコンパイラの追加

eclipce CDT ではデフォルトでgccが選択されていますが、gcc本体は入っていません。MinGwのgccを入れます。Cygwin経由だとCygwinを起動して経由させる必要があり、gccソースからvisual StudioでBuildするのもしんどいですし可能かナゾです。ぱっとWindows 64bit用の配布場所に辿りつけません。以下の場所から以下のfileをdownloadします。

解凍して分かりやすい場所( Program Files以外 )に置きます。

gcc に必要なライブラリ2つとmake も必要なので、その3つを GnuWin32 Project からdownloadして解凍して分かりやすい場所に置きます。

gcc、make、ライブラリ2つのパスを、WindowsのPATH環境変数に追加します。

eclipce CDT設定変更

eclipce CDTプロジェクト -> プロパティ を以下のように設定します。面倒なので HardwareDebug構成 を上書きしています。

お試しBuild

これで一応、クロスBuildできるようになりました。これである程度フラグ消し( H用語でコンパイルエラーを消すこと )までができるようになりました。

しかし組込み特有の絶対アドレスからキャストして実体参照など、OSありCでは際どいコードは通らないようなので、オプションの見直しが色々必要そうです。今更ながら、gcc RL78を使ったほうがよいかも、、、(でもそれじゃ面白くない)