AUTOSARによる開発 ~排他エリア(Exclusive Area)

電子制御ユニット(ECU)開発では、周辺デバイスやグローバル変数といった共有リソースへのアクセス時に、割込みやタスク間で排他処理が必要になることがあります。
AUTOSARには、SWC(Software Component)やBSW(Basic Software)開発時には排他処理を抽象化しておき、インテグレーション時に具体的な排他処理を決定する排他エリア(Exclusive Area)という仕組みがあります。今回は、この排他エリアについて紹介します。

AUTOSAR開発における排他処理

AUTOSARでは、SWCやBSWをソフトウエア部品として開発しておき、インテグレーション作業において必要な部品を集めて使用します。そのため、SWCやBSWを開発する時点では、どの機能に対して排他処理が必要となるかを決定することができません。 SWCが正しく実行されているかを監視するBSWであるWdgM(※1)を題材に、具体的に見てみましょう。

※1 Watchdog Manager:https://www.autosar.org/fileadmin/user_upload/standards/classic/4-0/AUTOSAR_SWS_WatchdogManager.pdf

BSWでは、主にタイミングに依存する処理を制御するためにMainFunctionというAPIを周期的に呼び出します。

WdgMでは、WdgM_MainFunctionというAPIになります。WdgM_MainFunctionを周期的に呼び出すことにより、SWCが想定したタイミングで実行されているかなどを監視します。また、SWCからはWdgM_CheckpointReachedというAPIを呼び出すことにより、引数で指定した監視対象の処理が実行されたことをWdgMに通知します。
WdgM_MainFunctionでは、SWCごとに設定された監視条件と、WdgM_CheckpointReachedの呼び出し状況から、正しく処理が実行されているかを判定するわけです。

WdgM_MainFunctionとWdgM_CheckpointReached内の処理では、SWCごとの監視状態を管理するデータを操作するので、WdgM_MainFunctionでデータを更新中に割込みが入り、WdgM_CheckpointReachedが実行されるとデータ不整合が発生する恐れがあります。これを防ぐために、WdgM_MainFunctionとWdgM_CheckpointReachedでは、排他処理を行う必要があります。

しかし、WdgM_MainFunctionを呼び出すタスクと、WdgM_CheckpointReachedを呼び出すタスクが同一優先度である場合はどうなるでしょうか?
同一優先度タスクが、タスク実行中に割込んで実行されることはありませんので、WdgM_MainFunction実行中にWdgM_CheckpointReachedが実行されるという状況は発生しません。この場合は、排他処理が不要になります。 つまり、WdgM_MainFunctionとWdgM_CheckpointReachedに排他処理を固定的に実装してしまうと、ECUのソフトウエア構成によっては、無駄な排他処理になってしまうわけです。

こういった状況を解決するために、排他エリアという排他処理を抽象化する仕組みを使用します。

排他メカニズム(Exclusive Mechanism)

排他エリアの説明をする前に、AUTOSARにおける排他処理を実現するためのメカニズム(排他メカニズム)について説明します。
AUTOSARでは、主にOS(※2)が提供する機能である割込み管理、リソース、スピンロックを使用して、排他処理を実現します。

※2 Operating System: https://www.autosar.org/fileadmin/user_upload/standards/classic/4-0/AUTOSAR_SWS_OS.pdf

割込み管理

OSが管理する割込み(ISR:Interrupt Service Routine)には、カテゴリ1ISRとカテゴリ2ISRの2種類があります。
カテゴリ1ISRは、割込みの禁止/許可に関するAPIのみを呼び出すことができ、割込みが発生してからリターンしてくるまで、OSは何も関与しないため、高速な割込み応答性が必要な場合に使用します。
カテゴリ2ISRは、多くのOSのAPIが使用可能です。レジスタ退避/復帰など、ユーザ定義の割込み処理を実行するための処理をOSが提供します。

これらの割込みに対して、OSは以下のAPIを提供します。

- SuspendAllInterrupts: すべての割込みを禁止する
- ResumeAllInterrupts: すべての割込みを許可する
- SuspendOSInterrupts: すべてのカテゴリ2ISRの割込みを禁止する
- ResumeOSInterrupts: すべてのカテゴリ2ISRの割込みを許可する

タスクを切り換えることができるのは、タスクを制御するAPIを呼び出せるカテゴリ2ISRのみですので、異なる優先度のタスク間で排他制御が必要な場合は、SuspendOSInterrupts/ResumeOSInterruptsによる排他区間内で、排他処理を実行すればよいことになります。
カテゴリ1ISRとも排他制御が必要な場合は、SuspendAllInterrupts/ResumeAllInterruptsを使用します。

リソース

リソースは、優先度上限プロトコルを用いた排他制御機能です。
OSのコンフィギュレーションで定義するリソースごとに、そのリソースを使用するタスクを指定しておくことで、各リソースの優先度の上限を決定しておきます。
ランタイムでは、リソースを取得したタスクの優先度が、対象リソースの上限まで引き上げられることで、排他区間だけ、他のタスクが実行状態とならないようにすることができます。
以下のAPIにより、リソースを取得/解放します。

- GetResource: リソースを取得する
- ReleaseResource: リソースを解放する

なお、リソースは、カテゴリ2ISRとの排他もできるように拡張してもよいと規定されています。

スピンロック

スピンロックは、マルチコア環境でのみ使用するコア間の排他制御機能です。
マルチコア環境では、複数のコアでタスクが並列して実行されますので、あるコアで割込み禁止としても、他のコアのタスクの処理を止めることはできません。そこで、全コアで共通の排他資源としてスピンロックを定義しておき、あるコアのタスクがスピンロックを取得している間は、別のコアのタスクはそのスピンロックを取得できず、スピン(ループ)してロックが取得できるのを待ちます。

以下のAPIにより、スピンロックを取得/解放します。

- GetSpinlock: スピンロックを取得する(取得できるまでスピンする)
- TryToGetSpinlock: スピンロックを取得する(取得できなかった場合はリターンする)
- ReleaseSpinlock: スピンロックを解放する

なお、AUTOSARでは、スピンロックごとに、スピンロック取得と同時に割込みも禁止するといった属性を指定することが可能となっています。

<注意事項>
AUTOSARのOSは、OSEK/VDX OS仕様の上位互換と規定されており、OSEK/VDX OS仕様の部分はAUTOSARの仕様書に記載されていません。
また、OSEK/VDX OS仕様は、ISOで標準化されたことにより、現在は一般公開されていません。
前述した機能のうち、スピンロック以外は、OSEK/VDX OS仕様で規定された機能となります。


排他処理の実装

では、WdgMを題材に、どのように排他処理を実装するのかを説明します。
以下は、WdgM_MainFunction、WdgM_CheckpointReachedの排他処理部分の実装イメージです。

※AliveSupervisionとは、SWC内の処理が正しいタイミングで実行されているかを監視するWdgMの機能の名称です。

  :
  SchM_Enter_WdgM_AliveSupervision();
   /*
    * AliveSupervisionに関連するデータの操作
    */
  SchM_Exit_WdgM_AliveSupervision();
   :

実装はシンプルで、RTE(※3)が提供するSchM_Enter、SchM_ExitというAPIを、排他区間の開始と終了のタイミングで呼び出すのみとなります。

※3 Runtime Environment:https://www.autosar.org/fileadmin/user_upload/standards/classic/4-0/AUTOSAR_SWS_RTE.pdf

インテグレーション作業において、各排他区間に必要な排他メカニズムが何であるかを検討した上で、RTEで各APIを生成することにより、ECUのソフトウエア構成に応じた必要最小限の排他処理とすることが可能となるわけです。

SchM_Enter、SchM_Exitは、以下のような命名規則で規定されており、上記の例ですと、<bsnp>が"WdgM"、<name>が"AliveSupervision"となります。

void SchM_Enter_<bsnp>[_<vi>_<ai>]_<name>()
void SchM_Exit_<bsnp>[_<vi>_<ai>]_<name>()

※詳細はRTEの仕様書(※3)を参照ください。

WdgM実装時は、「AliveSupervisionに関連するデータの操作を行うための排他区間がある」ということだけを決定し、SchM_Enter、SchM_Exitの命名規則に従って、WdgMを実装することになります。
もちろん、AliveSupervision以外のデータ操作時にも排他が必要であれば、同様のAPIを使用して排他処理を実装します。
このように、SchM_Enter、SchM_Exitを用いて排他区間を実装する仕組みが排他エリアとなります。

なお、上記はBSWの実装なので「SchM(BSW Scheduler Module)」というプレフィックスとなっていますが、SWCにおける排他エリアの場合は、プレフィックスが「Rte」となります。

排他エリア情報の提供

インテグレーターが適切な排他メカニズムを選択するためには、各SWCやBSWが排他エリアを有しているということをインテグレーターが知る手段が必要です。
SWCの場合はSoftware Component Template(※4)、BSWの場合はBSW Module Description Template(※5)で規定されたメタモデルを用いて定義します。

※4 https://www.autosar.org/fileadmin/user_upload/standards/classic/4-0/AUTOSAR_TPS_SoftwareComponentTemplate.pdf

※5 https://www.autosar.org/fileadmin/user_upload/standards/classic/4-0/AUTOSAR_TPS_BSWModuleDescriptionTemplate.pdf

以下、前述のWdgMが提供するAliveSupervisionという排他エリアの定義の抜粋となります。

  1:<BSW-MODULE-DESCRIPTION>
  2:   <SHORT-NAME>WdgM</SHORT-NAME>
  3:   <INTERNAL-BEHAVIORS>
  4:      <BSW-INTERNAL-BEHAVIOR>
  5:         <SHORT-NAME>InternalBehavior</SHORT-NAME>
  6:         <EXCLUSIVE-AREAS>
  7:            <EXCLUSIVE-AREA>
  8:               <SHORT-NAME>AliveSupervision</SHORT-NAME>
  9:               <DESC>
 10:                  <L-2>This exclusive area is ...</L-2>
 11:               </DESC>
 12:            </EXCLUSIVE-AREA>
 13:         </EXCLUSIVE-AREAS>
 14:         <ENTITYS>
 15:            <BSW-SCHEDULABLE-ENTITY>
 16:               <SHORT-NAME>WdgM_MainFunction</SHORT-NAME>
 17:               <CAN-ENTER-EXCLUSIVE-AREA-REFS>
 18:                  <CAN-ENTER-EXCLUSIVE-AREA-REF DEST="EXCLUSIVE-AREA">/WdgM/InternalBehavior/AliveSupervision</CAN-ENTER-EXCLUSIVE-AREA-REF>
 19:               </CAN-ENTER-EXCLUSIVE-AREA-REFS>
 20:            </BSW-SCHEDULABLE-ENTITY>
 21:            <BSW-CALLED-ENTITY>
 22:               <SHORT-NAME>WdgM_CheckpointReached</SHORT-NAME>
 23:               <CAN-ENTER-EXCLUSIVE-AREA-REFS>
 24:                  <CAN-ENTER-EXCLUSIVE-AREA-REF DEST="EXCLUSIVE-AREA">/WdgM/InternalBehavior/AliveSupervision</CAN-ENTER-EXCLUSIVE-AREA-REF>
 25:               </CAN-ENTER-EXCLUSIVE-AREA-REFS>
 26:            </BSW-CALLED-ENTITY>
 27:         </ENTITYS>
 28:      </BSW-INTERNAL-BEHAVIOR>
 29:   </INTERNAL-BEHAVIORS>
 30:</BSW-MODULE-DESCRIPTION>

1行目から「WdgM」に対する定義が始まります。
7~12行目で排他エリア「AliveSupervision」を定義しており、17~19、23~25行目で、WdgM_MainFunctionとWdgM_CheckpointReachedが排他エリア「AliveSupervision」を使用することを定義しています。

また、9~11行目のDESCにより、排他エリアの説明を記述することも可能ですので、WdgM_MainFunctionとWdgM_CheckpointReachedを同時に呼び出す場合に必要な排他エリアである旨の説明を記述しておくことで、インテグレーターに排他エリアの必要性などを伝えることができます。

もちろん、BSWに付属されているマニュアルに、各排他エリアの説明が記載されていることもあります。

なお、各BSWが有する排他エリアの数(粒度)や用途は、BSWの設計/実装に大きく依存することもあり、AUTOSARで標準化されていません。BSWベンダーごとに用意された排他エリアが異なることがありますので、ご注意ください。

排他エリアのコンフィギュレーション

SWC、BSWから提供された排他エリアの情報をもとに、インテグレーターは各排他エリアで必要な排他メカニズムを選択します。
排他エリアの設定方法は、RTEのEcucDefs(※6)で規定されています。

※6 富士ソフト技術コラム
「AUTOSARによる開発 ~Basic Softwareのコンフィギュレーション仕様の仕組み」
/blog/4061/

以下、排他エリアを設定するRteBswExclusiveAreaImpl部分の抜粋となります。
※本コラムでは、基本的にAUTOSARのR4.0.3を対象としていますが、R4.3でRteExclusiveAreaImplMechanismに"NONE"が追加されたため、以下のEcucDefsはR4.3のものを掲載しています。

  1:<ECUC-PARAM-CONF-CONTAINER-DEF UUID="ECUC:ecd2f711-51be-4b48-83a2-219528eaaa17">
  2:   <SHORT-NAME>RteBswExclusiveAreaImpl</SHORT-NAME>
  3:   <PARAMETERS>
  4:      <ECUC-ENUMERATION-PARAM-DEF UUID="ECUC:99e2df6b-46ef-9a25-3991-e9af1b370716">
  5:         <SHORT-NAME>RteExclusiveAreaImplMechanism</SHORT-NAME>
  6:         <LITERALS>
  7:            <ECUC-ENUMERATION-LITERAL-DEF UUID="ECUC:51458958-eb49-db2b-f050-9c1d28db40ae">
  8:               <SHORT-NAME>ALL_INTERRUPT_BLOCKING</SHORT-NAME>
  9:            </ECUC-ENUMERATION-LITERAL-DEF>
 10:            <ECUC-ENUMERATION-LITERAL-DEF UUID="ECUC:e903fa41-18a4-e28b-c6cf-d7ed12ccbde9">
 11:               <SHORT-NAME>NONE</SHORT-NAME>
 12:            </ECUC-ENUMERATION-LITERAL-DEF>
 13:            <ECUC-ENUMERATION-LITERAL-DEF UUID="ECUC:d888ea7b-03f2-e0d4-c266-d780b657d096">
 14:               <SHORT-NAME>OS_INTERRUPT_BLOCKING</SHORT-NAME>
 15:            </ECUC-ENUMERATION-LITERAL-DEF>
 16:            <ECUC-ENUMERATION-LITERAL-DEF UUID="ECUC:763f0200-5758-dccb-e54e-48cef5eb9190">
 17:               <SHORT-NAME>OS_RESOURCE</SHORT-NAME>
 18:            </ECUC-ENUMERATION-LITERAL-DEF>
 19:            <ECUC-ENUMERATION-LITERAL-DEF UUID="ECUC:18e1be81-8f60-e4a8-f673-9a0c24a561a9">
 20:               <SHORT-NAME>OS_SPINLOCK</SHORT-NAME>
 21:            </ECUC-ENUMERATION-LITERAL-DEF>
 22:         </LITERALS>
 23:      </ECUC-ENUMERATION-PARAM-DEF>
 24:   </PARAMETERS>
 25:   <REFERENCES>
 26:      <ECUC-REFERENCE-DEF UUID="ECUC:bfaccb50-3017-44d5-9c2c-692cbd375d3d">
 27:         <SHORT-NAME>RteBswExclusiveAreaOsResourceRef</SHORT-NAME>
 28:         <DESTINATION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR/EcucDefs/Os/OsResource</DESTINATION-REF>
 29:      </ECUC-REFERENCE-DEF>
 30:      <ECUC-REFERENCE-DEF UUID="ECUC:17fad2ad-eeff-411a-9b4a-2f8bee7c44f1">
 31:         <SHORT-NAME>RteBswExclusiveAreaOsSpinlockRef</SHORT-NAME>
 32:         <DESTINATION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR/EcucDefs/Os/OsSpinlock</DESTINATION-REF>
 33:      </ECUC-REFERENCE-DEF>
 34:      <!-- Foreign Reference Definition: RteBswExclusiveAreaRef -->
 35:      <ECUC-FOREIGN-REFERENCE-DEF UUID="ECUC:9a3b4142-244d-40d2-a461-6a6b3f605891">
 36:         <SHORT-NAME>RteBswExclusiveAreaRef</SHORT-NAME>
 37:         <DESTINATION-TYPE>EXCLUSIVE-AREA</DESTINATION-TYPE>
 38:      </ECUC-FOREIGN-REFERENCE-DEF>
 39:   </REFERENCES>
 40:</ECUC-PARAM-CONF-CONTAINER-DEF>

排他エリアは、RteBswExclusiveAreaImplというコンテナで設定します。
RteBswExclusiveAreaRefにて、設定対象とするSWC/BSW側の排他エリア(AliveSupervisionなど)を指定します。
そして、RteExclusiveAreaImplMechanismにて、以下の排他メカニズムの中から選択します。

ALL_INTERRUPT_BLOCKING SuspendAllInterrupts/ResumeAllInterruptsによる割込み禁止
NONE 何もしない(SchM_Enter/SchM_Exit(Rte_Enter/Rte_Exit)を空の関数/マクロとする等)
OS_INTERRUPT_BLOCKING SuspendOSInterrupts/ResumeOSInterruptsによる割込み禁止
OS_RESOURCE RteBswExclusiveAreaOsResourceRefで指定したリソースを取得/解放する
OS_SPINLOCK RteBswExclusiveAreaOsSpinlockRefで指定したスピンロックを取得/解放する

この設定により、Rteのジェネレータが、指定した排他メカニズムによるSchM_Enter、SchM_Exitを生成し、各SWC、BSW内の排他処理が決定されるわけです。

API呼び出し不要の排他制御

実は、AUTOSARにおける排他区間を開始/終了する方法は2種類あります。
本稿で紹介したのは、SchM_Enter/SchM_Exit(Rte_Enter/Rte_Exit)を明示的に呼び出すことで排他制御を行うCanEnterExclusiveAreaという方式となります。
もう1つは、RunsInsideExclusiveAreaという、APIの呼び出しが不要な方式となります。
RunsInsideExclusiveAreaの場合は、排他対象の関数を実行する前後に、SchM_Enter/SchM_Exit(Rte_Enter/Rte_Exit)相当の処理を行うコードをRteが生成します。
つまり、対象の関数全体を排他区間としたい場合は、RunsInsideExclusiveAreaを使うことで、関数内での排他用API呼び出しが不要となります。

排他エリアの設定には要注意

SWCやBSWの実装によっては、排他エリア内で他のコンポーネントが提供するAPIを呼び出す実装をしている場合があります。
この場合、選択する排他メカニズムによっては問題が起きる恐れがあります。
例えば、OSには、割込み禁止中には呼び出せないAPIが多く存在します。
あるコンポーネントAの排他エリア内で、コンポーネントBのAPIを呼び出していた場合に、コンポーネントBのAPIでOSのAPIを呼び出していたとします。
ここで、コンポーネントAの排他メカニズムに、割込み禁止を選択してしまうと、コンポーネントB内でのOSのAPI呼び出し時にエラーが発生することがあります。

このような問題を回避するために、対象コンポーネントのマニュアル等に記載された制限事項を確認するなど、排他エリアの設定には注意が必要です。

鴫原 一人博士(情報科学)
鴫原 一人(Kazuto Shigihara)

ASI事業部
次長 / エグゼクティブフェロー

この記事を読んだ人はこちらの記事も読んでいます。