The Swamp of ECU Development

ようこそ.あなたは 2983 人目のお客様です.キリ番踏んだら連絡してね.

このサイトはniiimがオープンな情報を元に適当なまとめた情報を掲載しています.間違いがあればご指摘頂けると助かります.

CAN Communication Buffering

はじめに

本稿ではAutosar CPのCanIfとCANのバッファ機能について紹介します.

CAN Diverは通常Canと表記されますが,混乱防止のためCanDrvと表記します.CanIfの上位モジュールは,Upper Layerとして表記します.

バッファに関する用語の定義

Hardware Object (HWO)CAN Controller内にある1つのPDUに対応するRAM領域.
主に以下の4つの設定項目が存在する:
 - ID
 - データ長
 - Handle Type (FullCAN or BasicCAN)
 - Object Type (Transmission or Reception)
FullCANHWOの種類の1つ.1つのHWOに対して1つのPDUを割当てる.
BasicCANHWOの種類の1つ.1つのHWOに対して複数のPDUを割当てる.
Hardware Transmission Handle (HTH)送信に用いるHWOを指すポインタ.1つのPDUに対して複数のHWOを割当てることもできる(SWS_Can_00403).
Hardware Reception Handle (HRH) 受信に用いるHWOを指すポインタ.

Autosarより引用して参考図を示します.次の図では8個のHWOが存在し,4つのHWOが4つのHRHと,2つのHWOが1つのHTHと割当たっています.この構成はOuter Priority Inversionを回避するために用いられます.

受信の際も同様です.

なお割当てる数はHTH, HRHにおいて,割当てるHWOの数はCanHwObjectCountと呼ばれます.

送信フロー

基本的な送信フロー次の通りです.

  1. UpperLayerは,CanIfに対して,CanIf_Transmitを呼出す.渡す情報は,CanIf上のIDととPduTye*の2つ.
  2. CanIfは,CanIf上のIDから,該当するHTHを探す.
  3. CanIfは,CanDrvに対して,Can_Writeを呼出す.渡す情報は,HTHとPduType*の2つ.
  4. CanDrvは,HTHから書込むMailboxを探し,データを書込む.書き込みに失敗した場合,CAN_BUSYを返す.
  5. CanIfは,Can_Writeの返戻値がCAN_BUSYであれば,バッファリング処理を行うことがある (当該節を参照)

CanDrvnの処理は割込み(Interrupt)でもタスク処理(Polling)でも処理できます.割込みの時のシーケンス図を,Autosar仕様から引用して示します.

送信完了通知

送信が完了すると,CanDrvは送信完了通知(TxConfirmation)を受取り,CanIfに通知します.CanDrvの送信完了通知の受取りは,割込み(Interrupt)かタスク処理(Polling)かを選択することができます.割込みの時のシーケンス図を,Autosar仕様から引用して示します.

送信完了通知を利用すれば,CanBusのレベルで正しく送信されたかを知ることができます.

このため,CanIfのコンフィグでは各フレームに対して,どのUpper Layerに対して送信完了通知を行うかや,その呼出し関数を指定することができるようになっています.

補足. CANの物理層のプロトコルでは,送信者がAckSlotをRecessiveにしておいて送信しておき,その部分を受信者がDominantに書換えることによって,受信者のうち少なくとも誰か一人が正しく受信したことが分かる仕組みとなっていました.送信完了通知はこれを利用します.従ってここでの「送信完了」とはAckSlotがDominantとなった,即ち受信者のうち誰か一人に正しく受信されたことことを意味します.

送信フレームのバッファリング

CanDrvのMailboxの書込みはCAN_BUSYで失敗するケースがあります.その原因は,例えば当該Mailboxに書込む瞬間において,より優先度の低いIDが多数あるケースです.この時,あるフレームに対する1回目のCan_Writeでは,該当するMailboxに書込まれるが,そのフレームはチャネルがBusyのため送信されず,同じフレームに対する2回目のCan_Writeでは,1つ目のフレームがまだ送信中の状態のためCAN_BUSYとなります.但しCAN Controllerによっては,Mailboxが上書きができ,CAN_BUSYとならないケースもあるので注意が必要です.

Can_Writeの返り値がCAN_BUSYであった時,CanIfは当該フレームがBasicCANに割当てられていれば,CanIfのバッファ(CanIfTxBuffer)にバッファリングを行います.なおバッファに既に前のフレームが存在する場合,最新のものに上書きされます.

バッファリングされたフレームの送信は送信完了通知の時に行います.「送信完了通知」の節で述べたように,送信完了通知は割込み(Interrupt)かタスク処理(Polling)が選べますが,Interruptの時の例をAutosar仕様書から引用して示します.

BasicCANに割当てられたフレームのバッファリングの具体例

1つの同一のBasicCANに割当てられたフレームA, Bが存在し,Upper Layerがシグナルの内容を変えてA1, B1, B2と送信要求を行うとします.この時,他の優先度の高いフレームによってバスが占有されているとします.

  1. A1送信時のCan_Writeの処理では,MailboxにA1を書込み,正常終了する.但しバスは占有されているため,A1はバス上に送信されない.
  2. B1送信時のCan_Writeの処理では,MailboxにまだA1が残っているため,CAN_BUSYとして応答する.
  3. CanIfはB1をCanIfTxBufferに保存する.
  4. B2送信時のCan_Writeの処理では,MailboxにまだA1が残っているため,CAN_BUSYとして応答する.
  5. CanIfはB2をCanIfTxBufferに保存する.B1は上書きされる.

バスの占有が解除されると,ECUはA1, B2の順にバス上に送信する.

FullCANに割当てられたフレームのバッファリング

FullCANに割当てられたフレームは,CanIfTxBufferが存在しません.このため,Can_Writeの戻り値がCAN_BUSYとなった場合は,バッファリング処理は存在せず破棄します.

但しMailboxには保存されるため,他のフレームによるバスの占有が起きた場合,その解除後にはMailboxのフレームのみ送信される形となります.この例を次に示します.

FullCANに割当てられたフレームCが存在し,Upper Layerがシグナルの内容を変えてC1, C2, C3と送信要求を行うとします.この時,他の優先度の高いフレームによってバスが占有されているとします.

  1. C1送信時のCan_Writeの処理では,MailboxにC1を書込み,正常終了する.但しバスは占有されているため,C1はバス上に送信されない.
  2. C2送信時のCan_Writeの処理では,MailboxにまだC1が残っているため,CAN_BUSYとして応答する.
  3. CanIfはC2を破棄する.
  4. C3送信時のCan_Writeの処理では,MailboxにまだC2が残っているため,CAN_BUSYとして応答する.
  5. CanIfはC3を破棄する.

バスの占有が解除されると,ECUはC1のみバス上に送信します.

受信フロー

CanDrvの処理は割込み(Interrupt)でもタスク処理(Polling)でも処理でき,フレームによって切替えることもできます(Mixed).Pollingでの処理フローは次の通りです.

  1. CanDrvは,CanIfに対して,CanIf_RxIndicationを呼出す.
  2. CanIfは,UpperLayerに対して,UpperLayer_RxIndicationを呼出す。

Pollingでのシーケンス図を示します.