【CanTp】車両診断通信 その30【シミュレーション⑰】

【CanTp】車両診断通信 その30【シミュレーション⑰】 車両診断通信

バックナンバーはこちら。
https://www.simulationroom999.com/blog/diagnostic-communication-backnumber/

はじめに

ISO-TPのシミュレーションをしよう。のシリーズ。
XLドライバライブラリの受信割り込みと送信完了割り込みの再現方法について。

登場人物

博識フクロウのフクさん

イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1

エンジニア歴8年の太郎くん

イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1

XLドライバライブラリの割り込みエミュレーションのソースコード

フクさん
フクさん

じゃ、前回の続き。

太郎くん
太郎くん

XLドライバライブラリを割り込みっぽくするんだっけ?

フクさん
フクさん

これはとっととコードを出してしまう。
全てのコードを載せるとえらいことになるんで、
スレッド関数の部分だけ

DWORD WINAPI CCANFunctions::RxThread(LPVOID par) 
{
	XLstatus		xlStatus;
	XLcanRxEvent	xlEvent;
	CCANFunctions *pThis;
	TStruct *pth;
	
	bThreadRun = TRUE;
	pth = (TStruct*) par;  
	pThis = (CCANFunctions *)pth->pThis;

	while (bThreadRun) { 

		WaitForSingleObject(pth->hMsgEvent,100);
	    
		xlStatus = XL_SUCCESS;
		unsigned short	flags;

		while (!xlStatus) {
			xlStatus = xlCanReceive(pth->xlPortHandle,  &xlEvent);	
			
			if ( xlStatus != XL_ERR_QUEUE_IS_EMPTY ) {
				flags = xlEvent.tag;
				
				switch( flags ){
				case XL_CAN_EV_TAG_RX_ERROR:
					// 受信エラー
					if( pThis->err_callback ){
						// エラー割り込み
						pThis->err_callback( pThis, &xlEvent );
					}
					break;
				case XL_CAN_EV_TAG_TX_ERROR:
					// 送信エラー
					if( pThis->err_callback ){
						// エラー割り込み
						pThis->err_callback( pThis, &xlEvent );
					}
					break;
				case XL_CAN_EV_TAG_TX_OK:
					// 送信完了
					if( pThis->tx_callback ){
						// 送信完了割り込み
						pThis->tx_callback( pThis, &xlEvent );
					}
					break;
				case XL_CAN_EV_TAG_RX_OK:
					// 受信
					if( pThis->rx_callback ){
						// 受信割り込み
						pThis->rx_callback( pThis, &xlEvent );
					}
					break;
				case XL_CAN_EV_TAG_CHIP_STATE:
					// BusOFF強制復帰
					pThis->CANGoOffBus();
					pThis->CANGoOnBus();
					break;
				default:
					break;
				}
			}
		}
	}
	return NO_ERROR; 
}

XLドライバライブラリの割り込みエミュレーション説明

太郎くん
太郎くん

動きがイメージできない・・・。

フクさん
フクさん

まぁそうだろうね。
ポイントは以下。
①WaitForSingleObject関数
②xlCanReceive関数
③switch文と各種コールバック

WaitForSingleObject関数

フクさん
フクさん

WaitForSingleObject関数はWin32APIの一つ。

イベントオブジェクトがシグナル状態になるか、
指定タイムアウトが過ぎることで戻ってくる関数。
つまりは、基本的にはここで止まっていることの方が多いと言える。

太郎くん
太郎くん

シグナル状態って?

フクさん
フクさん

イベントオブジェクトの場合は別スレッドでSetEvent関数で該当イベントオブジェクトを呼び出すことで、シグナル状態になる。
WaitForSingleObjectから戻った段階で非シグナル状態になんで、
SetEvent関数が呼ばれた回数分スレッド内の処理が実施されるイメージだね。

太郎くん
太郎くん

ほう。
ってことは、XLドライバライブラリの内部でCAN受信毎かCAN送信毎にSetEvent関数が呼ばれているんで、
そのタイミングでスレッドが1回動作することになるってことか。

フクさん
フクさん

その通り。

xlCanReceive関数

フクさん
フクさん

xlCanReceive関数はXLドライバライブラリのAPIの一つでCAN受信用関数。
今回の関数だとxlEvent変数に受信情報が格納される。
1フレームずつ取得するんだけど、
空の場合はXL_ERR_QUEUE_IS_EMPTYが戻り値になる。
WaitForSingleObjectを抜けてきた状態に於いて、
XL_ERR_QUEUE_IS_EMPTYが戻りになることは無いはずなんだけど、
一応、XL_ERR_QUEUE_IS_EMPTYではないことをチェックして次の判定に進んでいる。

太郎くん
太郎くん

まぁ、念のためのチェックは必要だよねー。
実はどっかで読み出されてるってことも有るかもしれないし。

switch文と各種コールバック

フクさん
フクさん

で、割り込みエミュレーションを実現している部分が
各種case文とコールバック関数

太郎くん
太郎くん

あーこれこれ。
xlEvent.tagってのにxlCanReceiveから取得したデータの意味が入ってると思って良いのかな?

フクさん
フクさん

うん。あってるよ。
xlCanReceiveは受信関数ではあるんだけど、
実際には送信フレームやエラー情報も1つのフレームという体で取得できるんだ。

太郎くん
太郎くん

なるほど。
それで、xlEvent.tagの情報を元にswitchで分岐してそれぞれ該当メソッドを呼び出しているわけか。

フクさん
フクさん

今回提示したコード上では載せてないけど、
この先で上位から渡されたコールバック関数を呼ぶような処理をいれると、
割り込み相当の動作になる。

太郎くん
太郎くん

あ、割り込みの実現はスレッドでやっているってことか!

フクさん
フクさん

割り込みとスレッドは異なる概念ではあるけれども、
別の処理に切り替えるという特性だけ利用している感じだね。
こうすることで上位のAUTOSAR-CanTpからすると割り込みが来たように見える
ってわけだ。

太郎くん
太郎くん

あと、XL_CAN_EV_TAG_CHIP_STATEの場合になんかBusOffしてからBusOnするような処理が入ってるけど、これは何?

フクさん
フクさん

virtual CAN Busだと気にしなくて良いんだけど、
実際の物理的なCANの場合、ハーネスの抜き差しでCANがBusOFFになって復帰しないことがあるんだよね。
それを強制的に復帰させるためのおまじない。

太郎くん
太郎くん

おまじないって・・・。

フクさん
フクさん

ホントはCANのエラーアクティブ、エラーパッシブ、バスオフの状態を意識する必要があるんだけど、ここでは省略だ。

太郎くん
太郎くん

まぁおまじないとしておいた方が安全な気がしてきた。

まとめ

フクさん
フクさん

まとめだよ。

  • 割り込みエミュレーションのコードを提示。
  • WaitForSingleObjectでシグナル待ち。
  • xlCanReceiveで受信、送信、エラーの各種情報を取得。
  • xlEvent.tagで各種処理に振り分け。

バックナンバーはこちら。

コメント

タイトルとURLをコピーしました