バックナンバーはこちら。
https://www.simulationroom999.com/blog/diagnostic-communication-backnumber/
はじめに
ISO-TPのシミュレーションをしよう。のシリーズ。
A-COMSTACKからCanTpだけを引っこ抜いてくる。
登場人物
博識フクロウのフクさん

イラスト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
どれがAUTOSAR-CanTp?

さて、A-COMSTACKからCanTpだけを引っこ抜いてみよう。

具体的にはどうするの?

CanTpの本体はすでに分かってて、
その名もずばりcantp.c

確かにそのままだね。

ただし、cantp.cだけで閉じてるわけじゃなく、
各種ヘッダファイルが芋づる式に必要になるはずなんだよねー。
簡単に言うと、以下の流れになる。
①cantp.cを持ってくる
②cantp.cのビルドが通るようにヘッダファイルを集めてくる

②が大変そうだなぁ。

とりあえずやってみよう。
必要なファイル群

なんとか、ビルドが通るようになった・・・。

とりあえず、必要になったヘッダファイルを書きならべてみよう。
Compiler_Cfg.h
ComStack_Types.h
MemMap.h
Os.h
Platform_Types.h
Rte_Os_Type.h
Rte_Type.h
Std_Types.h
t_syslog.h
CanTp.h
CanTp_Cbk.h
CanTp_Cfg.h
Compiler.h
SchM_CanTp.h
CanIf.h
PduR_CanTp.h
※ TOPPERS ATK2の上で動作することを前提とした環境であるため、そこからヘッダを持ってくる必要もある。
TOPPERS ATK2

あとはmain関数とかタイマ割り込みとか排他制御を実現するstubを用意しておけばとりあえずOKかな。
タイマ割り込みエミュレーション

main関数が必要なのはわかるけど、
タイマ割り込みと排他制御はどう実現するの?

まずタイマ割り込みだけど、
Windowsのマルチメディアタイマーってのを使う。
具体的に言うと、timeSetEventってAPIを使用する。


あれ?
普通のタイマーAPIとは違うの?

うん。似てるし、使い方もコールバック式であれば一緒かな。
ただ、裏でリアルタイムスレッドってのが回ってるみたいで
通常タイマより遥かに精度が良い。
今回は1[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, 1, (LPTIMECALLBACK) callback, (DWORD) NULL, TIME_PERIODIC);
if(timer == 0) { printf("タイムイベントの生成に失敗\n"); exit(0); }
// ループ
while(1) {
Sleep(5000);
}
// タイムイベントの終了
timeKillEvent(timer);
}

なんか終了しないコードになってるけどいいの?

まぁ今回はプログラムの終了条件が無いんでね。
プロセスごと終了する前提なんで、後始末は雑になってる。

(うーん、良い子のみんなはマネするなよ!系だな。)

とりあえず、これでmsオーダーのタイマ割り込み相当のエミュレーションはできるってことになる。
排他制御

あと、排他制御は?

これもWin32APIを使う。
具体的にはMutex。


AUTOSARのコード側でWindows関連のヘッダをインクルードすると
型定義が衝突したりするんで、一度関数でラップして別ソースとして切り離しておいた方が良いね。
具体的なコードにすると以下。
void* _CreateMutex(void* lpMutexAttributes, int bInitialOwner,char* lpName)
{
return CreateMutex( (LPSECURITY_ATTRIBUTES)lpMutexAttributes, bInitialOwner, lpName);
}
unsigned int _WaitForSigleObject(void* hHandle, unsigned int dwMilliseconds )
{
return WaitForSingleObject( hHandle,dwMilliseconds);
}
int _ReleaseMutex( void* hMutex )
{
return ReleaseMutex( hMutex );
}

使いどころとはどうなるの?

割り込みエミュレーションしたコールバック関数群の入り口と出口に設定だね。
たとえば受信割り込みコールバックだと以下な使い方になる。
int rx_interrupt( void *param, canMessage* msg )
{
_WaitForSigleObject( hMutex,-1);
/* なにかしらの処理 */
_ReleaseMutex(hMutex);
return 0;
}

あーホントに入り口と出口だね。

でもこれだと他の割り込みが入らない状態になるけど?

まぁ多重割込までエミュレーションしようと思ったらこれだとダメだけど、
今回はCanTpが割り込みと認識する程度で良いんで、
多重割込は意識しなくても良いかな。

一応、最低限の足回りは揃った感じかな。
次回からAUTOSARの仕様と向き合ることになると思うよ。

(不安しかない)
まとめ

まとめだよ。
- A-COMSTACKのCanTpの本体はcantp.c。
- 多くのヘッダファイルも持ってくる必要がある。
- タイマ割り込み、排他はWin32APIで実現。
バックナンバーはこちら。
コメント
上記ヘッダファイルについて、Os.hなど一部ファイルは、a-comstackのフォルダ内になかったのですが、a-comstack以外にもダウンロードする必要がありますか(あるいは自前で用意する形でしょうか。)
当時の状況としてはうろ覚えである点、ご了承ください。
基本的にはA-COMSTACKから取得したヘッダー群という認識でいます。
しかし、当時とパッケージ内容部の状況が変わった可能性もあります。
Os.hに関してはTOPPERS ATK2にも同様の物が入っているはずなので、そちらを参照してみてください。