【XCP】最小構成のMBD事例 第2章 その177【XCP Basic㉛】

【XCP】最小構成のMBD事例 第2章 その177【XCP Basic㉛】 事例
【XCP】最小構成のMBD事例 第2章 その177【XCP Basic㉛】

バックナンバーはこちら。
https://www.simulationroom999.com/blog/model-based-of-minimum-2-backnumber/

はじめに

前回はDAQパケット送信周期の精度が悪い理由を確認した。
イベントチャンネルがそもそも15[ms]駆動になっており、
それの原因がSleep(10)。
Sleep(10)は「少なくとも10[ms]以上待つことを保証」であり、実際は15[ms]で返ってくることが多い。
これがDAQパケットの15[ms]送信周期の大本の原因となる。

これに対して小手先の修正ではどうにもならないが、
ある程度の対策も考えているのでそれを確認していく。

登場人物

博識フクロウのフクさん

指差しフクロウ

イラスト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

DAQパケット送信周期精度改善の方針

太郎くん
太郎くん

で、改善方針はどうなるの?

フクさん
フクさん

まぁ時間精度に関わるところだし、
実は今までもやって来た手法ではあるのだが、
マルチメディアタイマを使用する。

太郎くん
太郎くん

あー、何回か使ったねー。
実績としては1[ms]周期ってのも作れたはず。

フクさん
フクさん

そうそう。
その実績があるんで、今回も採用って感じだ。

修正コード

太郎くん
太郎くん

で、具体的な修正コードは?

フクさん
フクさん

一応私の方で用意して見た。
マルチメディアタイマから1[ms]周期で呼び出されるコールバック関数はこんな感じだ。

// Task Sheduler
void main_handler() {

	WORD i = 0;
	WORD j = 0;

	gTimer += 1;

	/* 10ms Task ECU Simulation */
	if ((gTimer % 10) == 0) {
		ecuCyclic();
	}
	/* Event Channel 1 is cyclic 1 ms */
#ifdef XCP_ENABLE_DAQ
	XcpEvent(3);
#endif

	/* Event Channel 1 is cyclic 10 ms */
	if ((gTimer % 10)==0) {
#ifdef XCP_ENABLE_DAQ
#ifdef XCP_DPRAM_SERVER
		dpramServerTriggerTask(1);
#else
		XcpEvent(1);
#endif
#endif
	}

	if (gTimer % 100 == 0) {

		/* Event Channel 2 is cyclic 100 ms */
#ifdef XCP_ENABLE_DAQ
		XcpEvent(2);
#endif

		/* Flush every 100ms */
		ApplXcpSendFlush();

	}
	/* XCP driver background processing */
#ifdef XCP_ENABLE_CHECKSUM
	XcpBackground();
#endif  

	return 0;
}
フクさん
フクさん

そして、マルチメディアタイマ起動側のコードはこれ。
xcpsim.cのmain関数に差し込むコードになるな。

// MarutimediaTimer Start
_timeBeginPeriod(1);
setcallback(main_handler);
フクさん
フクさん

ちなみに、

Windows依存のヘッダとの衝突が心配だったので、stub.cというソースコードを作ってその中でWindowsAPIを呼ぶようにしている。

void (*_pcallback)();

void _timeBeginPeriod(DWORD ms)
{
	timeBeginPeriod(ms);
}

// タイムイベントとして呼び出されるコールバック関数
static void CALLBACK 
callback(unsigned int timerID, unsigned int msg, unsigned int usrParam, unsigned int dw1, unsigned int dw2) 
{
	_pcallback();
}

void setcallback( void (*pcallback)())
{
   unsigned int timer;

   _pcallback = pcallback;
   // タイムイベントの開始
   timer = timeSetEvent(1, 0, (LPTIMECALLBACK) callback, (DWORD) NULL, TIME_PERIODIC);
   if(timer == 0) { printf("タイムイベントの生成に失敗\n"); exit(0); }

}

修正コードについてあれこれ

太郎くん
太郎くん

whileループだったものがコールバックになった感じだね。
思ったほどのガラチェンって感じもしないね。

太郎くん
太郎くん

あと、イベントチャンネル3に紐づいているXcpEvent(3)が本当の意味で1[ms]で呼ばれることになるから、1[ms]周期のDAQパケットも送ろうと思えば送れるってとこか。

フクさん
フクさん

そうだね。
元々の実装だとSleep(10)毎に10回のXcpEvent(3)の呼び出しで仮の実装だったけど、
今回は1[ms]のコールバック毎に必ず呼び出されるので1[ms]は保証されると思って良いだろう。

太郎くん
太郎くん

次回は実際に動かしてみるってところかな。

まとめ

フクさん
フクさん

まとめだよ。

  • DAQパケット送信周期精度改善の方針を決めた。
    • 時間精度を引き上げるためマルチメディアタイマを使用。
      • 1[ms]精度の過去実績あり。
  • Sleep(10)を挟んだWhileループをマルチメディアタイマによる1[ms]コールバックに変更。
    • これに伴い10[ms]周期だけでなく、イベントチャンネル3も1[ms]保証ができる。

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

コメント

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