0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AUTOSAR Scheduler Module (SchM), RTE and Zero Copy with ChatGPT

Last updated at Posted at 2025-10-13

AUTOSARのRTEのSchemをソースコード付きで説明してください。

もちろんです。まずはAUTOSARのRTE(Runtime Environment)の概要を押さえてから、具体的な構造(スキーマ)とソースコード例を示します。わかりやすくCコード中心で説明します。

  1. AUTOSAR RTEの概要
    RTEは、AUTOSARアーキテクチャにおけるアプリケーションソフトウェア(SWC: Software Component)と基盤ソフトウェア(BSW: Basic Software)間の仲介層です。
    RTEの主な役割は以下です:
    SWC間通信の抽象化(コンポーネント間のポート通信)
    SWCとハードウェア・OSの依存性の分離
    タスク管理(スケジューリング)やイベント管理の提供
  2. RTEのスキーマ(構造)
    RTEは、AUTOSAR仕様に基づき各SWCに対して専用のRTEヘッダ・ソースが生成されます。
    典型的なRTEスキーマは以下の要素で構成されます:
    SWC1 SWC2
    | |
    Port Port
    | |
    +-----RTE-----+
    |
    RTE API Layer
    |
    BSW Services
    |
    ECU Drivers
    Port: SWCが外部とやり取りするインターフェース
    RTE API: SWCから呼ばれる関数群(読み取り・書き込み・呼び出し)
    BSW Services: OSや通信サービスなど
    ECU Drivers: 実際のハードウェア制御
  3. RTE APIの例
    たとえば、EngineControlというSWCがあり、EngineSpeedというデータを別SWCに送信する場合:
    a) RTEヘッダ(Rte_EngineControl.h)
    #ifndef RTE_ENGINECONTROL_H
    #define RTE_ENGINECONTROL_H

#include "Rte_Type.h"

/* SWCからポートを通じてデータ送信 */
Std_ReturnType Rte_Write_EngineSpeed(uint16 data);

/* SWCが受信する場合 /
Std_ReturnType Rte_Read_ThrottlePosition(uint16
data);

#endif
b) RTEソース(Rte_EngineControl.c)
#include "Rte_EngineControl.h"
#include "Rte_Internal.h"

Std_ReturnType Rte_Write_EngineSpeed(uint16 data)
{
/* 実際にはRTE内部のバッファや通信サービスを通じて転送 */
Rte_Internal_EngineSpeed = data;
return E_OK;
}

Std_ReturnType Rte_Read_ThrottlePosition(uint16* data)
{
if(data == NULL) return E_NOT_OK;
*data = Rte_Internal_ThrottlePosition;
return E_OK;
}
4. RTEの生成と使用
Arxml定義: SWCのポート、データ型、通信関係をARXMLで定義
RTE生成ツール: AUTOSARツール(Vector DaVinci, EB tresosなど)がARXMLからRTEソースを生成
アプリケーション実装:
#include "Rte_EngineControl.h"

void EngineControl_MainFunction(void)
{
uint16 throttle;
if(Rte_Read_ThrottlePosition(&throttle) == E_OK)
{
uint16 engineSpeed = throttle * 10; // 単純制御例
Rte_Write_EngineSpeed(engineSpeed);
}
}
5. ポイントまとめ
RTEはSWC間通信の抽象化レイヤ
RTE APIは自動生成されるため、SWCはハードウェアやOS依存なしで動作可能
RTE内部はバッファ管理・イベント通知・タスク起動などを行う
実際の通信はCOMモジュールやECUドライバに委譲
もしよければ、次のステップとしてRTEとOSタスク・イベントの関係を図にしたPlantUMLも作れます。
作ってほしいですか?

はい。

了解です。では、AUTOSAR RTEとOSタスク・イベントの関係をPlantUMLで図にします。RTEがどのようにタスクやイベントと連携してSWCを呼び出すかを表現します。
@startuml
title AUTOSAR RTEとOSタスク・イベントの関係

package "ECU" {

package "OS" {
[Task_EngineControl] as TaskEC
[Task_ThrottleMonitor] as TaskTM
[Event_EngineUpdate] as EventEU
}

package "RTE" {
[Rte_EngineControl] as RTEEC
[Rte_ThrottleMonitor] as RTETM
}

package "SWC" {
[SWC_EngineControl] as SWCEC
[SWC_ThrottleMonitor] as SWCTM
}

package "BSW" {
[COM Module] as COM
[ECU Drivers] as ECU
}

' タスク → RTE → SWC
TaskEC --> RTEEC : call
TaskTM --> RTETM : call

' RTE → SWC
RTEEC --> SWCEC : invoke Runnable
RTETM --> SWCTM : invoke Runnable

' SWC → RTE → COM → ECU
SWCEC --> RTEEC : Rte_Write()
RTEEC --> COM : send signal
COM --> ECU : send to HW

SWCTM --> RTEEC : Rte_Write() (EngineSpeed)
RTEEC --> EventEU : set event

' イベント → タスク
EventEU --> TaskEC : activate

@enduml
図の解説
OSタスク
Task_EngineControl、Task_ThrottleMonitor は周期的/イベント駆動で実行される。
RTE
各SWC専用RTE(Rte_EngineControlなど)がタスクから呼ばれる。
SWCのRunnable呼び出し、データの読み書きを仲介。
SWC
実際のアプリケーションロジックを実行。
RTE APIで他のSWCやCOMモジュールにデータ送信。
COM/ECU
CANやLINなどの通信モジュール、ハードウェア制御を行う。
イベント
SWCの状態変化やデータ更新に応じてOSタスクを起動。
この図をもとに、RTEはOSのタスク・イベントと密接に連携しつつ、SWC間通信を抽象化する層であることがわかります。
希望であれば、このPlantUMLにRTE内部のバッファ構造やデータフローも追加して、より詳細なRTEの動作図も作れます。作りますか?

Schmをソースコード付きで説明してください。

なるほど。「RTEのSchema(構造・スキーマ)をソースコード付きで」という意味ですね。では、AUTOSAR RTEの**SWC側のSchema(Runnable、Port、Data Elementの構造)**をCコード例と一緒に詳しく示します。

  1. RTE Schemaの概念
    RTEのスキーマ(Schema)とは、各SWCが利用するRTE APIの構造です。
    主な構成要素は:
    Ports
    SWCが外部とやり取りするインターフェース
    Sender/Receiver Port: データ送受信
    Client/Server Port: サービス呼び出し
    Data Elements
    Portでやり取りされるデータ
    Runnable
    OSから呼ばれるSWCの関数(処理単位)
    Events
    Runnableの起動条件(周期、データ更新など)
  2. Schema例(Cコード)
    例えば、EngineControl SWCでスロットル位置を読み、エンジン回転数を出力するケースを考えます。
    a) データ型定義(Rte_Type.h)
    #ifndef RTE_TYPE_H
    #define RTE_TYPE_H

typedef unsigned short uint16;
typedef unsigned char Std_ReturnType;

#define E_OK 0
#define E_NOT_OK 1

#endif
b) RTEヘッダ(Rte_EngineControl.h)
#ifndef RTE_ENGINECONTROL_H
#define RTE_ENGINECONTROL_H

#include "Rte_Type.h"

/* Sender/Receiver Port: EngineSpeed送信 */
Std_ReturnType Rte_Write_EngineSpeed(uint16 data);

/* Receiver Port: ThrottlePosition受信 /
Std_ReturnType Rte_Read_ThrottlePosition(uint16
data);

/* Runnable宣言 */
void EngineControl_MainFunction(void);

#endif
c) RTEソース(Rte_EngineControl.c)
#include "Rte_EngineControl.h"

/* RTE内部バッファ */
static uint16 Rte_Internal_ThrottlePosition = 0;
static uint16 Rte_Internal_EngineSpeed = 0;

Std_ReturnType Rte_Write_EngineSpeed(uint16 data)
{
Rte_Internal_EngineSpeed = data;
return E_OK;
}

Std_ReturnType Rte_Read_ThrottlePosition(uint16* data)
{
if(data == NULL) return E_NOT_OK;
*data = Rte_Internal_ThrottlePosition;
return E_OK;
}
d) SWC Runnable(SWC側の実装)
#include "Rte_EngineControl.h"

void EngineControl_MainFunction(void)
{
uint16 throttle;

/* Receiver Portからデータ取得 */
if(Rte_Read_ThrottlePosition(&throttle) == E_OK)
{
    /* 単純制御: エンジン回転数計算 */
    uint16 engineSpeed = throttle * 10;
    
    /* Sender Portを通じてデータ送信 */
    Rte_Write_EngineSpeed(engineSpeed);
}

}
3. Schemaのまとめ
Schema要素 説明
Port SWCの外部インターフェース。Sender/Receiver, Client/Serverがある
Data Element Portでやり取りされる変数(例:ThrottlePosition, EngineSpeed)
Runnable OSから呼び出される処理単位(例:EngineControl_MainFunction)
Event Runnableを起動する条件(周期、データ受信など)
RTE API Portを通じてデータアクセス・サービス呼び出しを提供する関数群
この構造を理解すると、RTEの自動生成コードの中身がどうなっているか、SWCはどのようにRTEを通じて通信しているかが明確になります。
もしよければ、次のステップとしてこのSchemaをPlantUMLで図解して、Runnable・Port・RTEの関係を可視化することもできます。
作りますか?

ごめんなさい。Scheduler Module (SchM) をソースコード付きでお願いします。

なるほど、「SchM(Scheduler Module)」ですね。AUTOSARのBSWの一部で、タスク排他制御やクリティカルセクションの管理を行うモジュールです。RTEとは異なり、OSタスクや割り込みとの調整を行います。では、ソースコード例と共に詳しく説明します。

  1. SchMの概要
    SchM (Scheduler Module) は、主に以下の役割を持ちます:
    Exclusive Areaの制御
    複数タスクや割り込みからの排他制御
    CPU依存の実装で、OSのSuspend/Resume機能などを使う
    クリティカルセクション管理
    SWCやBSWモジュールが安全に共有リソースにアクセスできるようにする
    タスク保護
    タイミング依存の処理が割り込みで中断されないようにする
  2. SchMの基本的な構造
    典型的には以下のようなAPIがあります。
    API名 役割
    SchM_Enter_(Area) クリティカルセクション開始
    SchM_Exit_(Area) クリティカルセクション終了
    : 対象BSWモジュール名(例:RTE, Can, Adcなど)
    Area: Exclusive Area番号(複数管理可能)
  3. ソースコード例
    a) ヘッダ(SchM_Rte.h)
    #ifndef SCHM_RTE_H
    #define SCHM_RTE_H

#include "Std_Types.h"

/* Exclusive Area定義 */
typedef enum {
RTE_EXCLUSIVE_AREA_0 = 0,
RTE_EXCLUSIVE_AREA_1
} SchM_ExclusiveAreaType;

/* API */
void SchM_Enter_Rte(SchM_ExclusiveAreaType area);
void SchM_Exit_Rte(SchM_ExclusiveAreaType area);

#endif
b) ソース(SchM_Rte.c)
#include "SchM_Rte.h"
#include "Os.h" /* OSのSuspend/Resume APIを仮定 */

static uint8 Rte_ExclusiveCounter[2] = {0, 0};

/* クリティカルセクション開始 /
void SchM_Enter_Rte(SchM_ExclusiveAreaType area)
{
/
再入可能カウンタを使用 /
if(Rte_ExclusiveCounter[area] == 0) {
SuspendAllInterrupts(); /
OS割り込み停止 */
}
Rte_ExclusiveCounter[area]++;
}

/* クリティカルセクション終了 /
void SchM_Exit_Rte(SchM_ExclusiveAreaType area)
{
if(Rte_ExclusiveCounter[area] > 0) {
Rte_ExclusiveCounter[area]--;
if(Rte_ExclusiveCounter[area] == 0) {
ResumeAllInterrupts(); /
OS割り込み再開 */
}
}
}
4. 使用例(RTE内での呼び出し)
#include "SchM_Rte.h"
#include "Rte_EngineControl.h"

void EngineControl_MainFunction(void)
{
uint16 throttle;

/* クリティカルセクション開始 */
SchM_Enter_Rte(RTE_EXCLUSIVE_AREA_0);

if(Rte_Read_ThrottlePosition(&throttle) == E_OK)
{
    uint16 engineSpeed = throttle * 10;
    Rte_Write_EngineSpeed(engineSpeed);
}

/* クリティカルセクション終了 */
SchM_Exit_Rte(RTE_EXCLUSIVE_AREA_0);

}
5. ポイントまとめ
SchMは排他制御専用モジュール
OSのSuspend/Resume APIと連携
再入可能(ネスト可能)クリティカルセクションをサポート
モジュール単位で生成
SchM_ の形式でBSWやRTEごとに生成される
BSWやRTE内で使用
SWCは直接使わないことが多い
RTE内部やBswモジュールが共有リソースを安全に扱うために利用
希望であれば、このSchMのRTEやOSタスクとの関係をPlantUMLで図解して、Exclusive Areaがどのように保護されるか可視化することもできます。
作りますか?

SchM_を具体例でお願いします。

わかりました。では、AUTOSARの SchM_ の具体例 を示します。ここでは典型的な RTE用 SchM_Rte と CANドライバ用 SchM_Can を例に、Cコードで具体的なExclusive Area管理を示します。

  1. SchM_Rte の例
    a) ヘッダ(SchM_Rte.h)
    #ifndef SCHM_RTE_H
    #define SCHM_RTE_H

#include "Std_Types.h"

/* Exclusive Area定義 */
typedef enum {
RTE_EXCLUSIVE_AREA_0 = 0,
RTE_EXCLUSIVE_AREA_1
} SchM_ExclusiveAreaType;

/* API */
void SchM_Enter_Rte(SchM_ExclusiveAreaType area);
void SchM_Exit_Rte(SchM_ExclusiveAreaType area);

#endif
b) ソース(SchM_Rte.c)
#include "SchM_Rte.h"
#include "Os.h" /* OSのSuspend/Resume APIを仮定 */

static uint8 Rte_ExclusiveCounter[2] = {0, 0};

void SchM_Enter_Rte(SchM_ExclusiveAreaType area)
{
if(Rte_ExclusiveCounter[area] == 0) {
SuspendAllInterrupts(); /* 割り込み停止 */
}
Rte_ExclusiveCounter[area]++;
}

void SchM_Exit_Rte(SchM_ExclusiveAreaType area)
{
if(Rte_ExclusiveCounter[area] > 0) {
Rte_ExclusiveCounter[area]--;
if(Rte_ExclusiveCounter[area] == 0) {
ResumeAllInterrupts(); /* 割り込み再開 */
}
}
}
c) 使用例
#include "SchM_Rte.h"
#include "Rte_EngineControl.h"

void EngineControl_MainFunction(void)
{
uint16 throttle;

SchM_Enter_Rte(RTE_EXCLUSIVE_AREA_0);

if(Rte_Read_ThrottlePosition(&throttle) == E_OK) {
    Rte_Write_EngineSpeed(throttle * 10);
}

SchM_Exit_Rte(RTE_EXCLUSIVE_AREA_0);

}
2. SchM_Can の例(CANドライバ用)
AUTOSARのCANモジュールでも同様の構造を持ちます。
a) ヘッダ(SchM_Can.h)
#ifndef SCHM_CAN_H
#define SCHM_CAN_H

#include "Std_Types.h"

typedef enum {
CAN_EXCLUSIVE_AREA_0 = 0
} SchM_CanExclusiveAreaType;

void SchM_Enter_Can(SchM_CanExclusiveAreaType area);
void SchM_Exit_Can(SchM_CanExclusiveAreaType area);

#endif
b) ソース(SchM_Can.c)
#include "SchM_Can.h"
#include "Os.h"

static uint8 Can_ExclusiveCounter[1] = {0};

void SchM_Enter_Can(SchM_CanExclusiveAreaType area)
{
if(Can_ExclusiveCounter[area] == 0) {
SuspendAllInterrupts(); /* 割り込み停止 */
}
Can_ExclusiveCounter[area]++;
}

void SchM_Exit_Can(SchM_CanExclusiveAreaType area)
{
if(Can_ExclusiveCounter[area] > 0) {
Can_ExclusiveCounter[area]--;
if(Can_ExclusiveCounter[area] == 0) {
ResumeAllInterrupts(); /* 割り込み再開 */
}
}
}
c) 使用例(CAN送信処理内)
#include "SchM_Can.h"
#include "Can.h"

void Can_SendMessage(uint8 channel, uint8 data)
{
SchM_Enter_Can(CAN_EXCLUSIVE_AREA_0);

/* CAN送信処理 */
Can_Write(channel, data);

SchM_Exit_Can(CAN_EXCLUSIVE_AREA_0);

}
3. ポイントまとめ
SchM_ はモジュール単位の排他制御API
Exclusive Areaごとにネスト可能なクリティカルセクションを実現
RTEやCANなど、BSWモジュール内部で共有リソース保護に使用
実装は通常 SuspendAllInterrupts / ResumeAllInterrupts で割り込み管理する
希望であれば、これら SchM_ のRTEやタスクとの関係をPlantUMLで図解して、Exclusive Areaがどのように保護されるか可視化することもできます。
作りますか?

schm_enter, schm_exit, rte_enter, rte_exit, rte_start, rte_stopの関係がくわかりません。ありがちな例をソースコードでお示しください。

なるほど、AUTOSAR BSW/RTEの SchM_Enter / SchM_Exit と Rte_Enter / Rte_Exit、さらに Rte_Start / Rte_Stop の関係 がわかりにくいということですね。
典型的な使用例をCコードで示して整理します。

  1. 役割の整理
    関数 役割
    SchM_Enter_(Area) モジュール単位のExclusive Area(クリティカルセクション)開始。CPUの割り込み制御などを行う。
    SchM_Exit_(Area) モジュール単位のExclusive Area終了。
    Rte_Enter_(Area) RTE内部でExclusive Areaを開始。内部的にSchMを呼ぶことが多い。
    Rte_Exit_(Area) RTE内部でExclusive Area終了。
    Rte_Start / Rte_Stop RTEの初期化・開始・停止を行う。OSタスク・タイマーなどを起動・終了させる。
    ポイント:
    SchM_ は BSW内部の低レベル排他制御
    Rte_ は SWCとRTEの間の排他・バッファ保護
    Rte_Start/Stop は システム起動/終了 に使う
  2. ありがちな例(EngineControl SWC)
    a) RTEの初期化と開始
    #include "Rte.h"

int main(void)
{
/* OS初期化など後にRTE初期化 */
Rte_Init();

/* RTEスタート: タスクやタイマーの起動 */
Rte_Start();

/* メインループ */
while(1)
{
    /* OSスケジューラにより周期タスクが起動 */
}

/* RTE停止(システム終了時) */
Rte_Stop();

return 0;

}
b) SWC Runnable内でのRTE/SchM利用例
#include "Rte_EngineControl.h"
#include "SchM_Rte.h"

void EngineControl_MainFunction(void)
{
uint16 throttle;
uint16 engineSpeed;

/* ---------------------------
   1. RTE Exclusive Area開始
   --------------------------- */
Rte_Enter_Rte(RTE_EXCLUSIVE_AREA_0);

/* ---------------------------
   2. SchM Exclusive Area開始(内部リソース保護)
   --------------------------- */
SchM_Enter_Rte(RTE_EXCLUSIVE_AREA_0);

/* Throttleデータを読む */
if(Rte_Read_ThrottlePosition(&throttle) == E_OK)
{
    engineSpeed = throttle * 10;
    /* EngineSpeedを書き込む */
    Rte_Write_EngineSpeed(engineSpeed);
}

/* ---------------------------
   3. SchM Exclusive Area終了
   --------------------------- */
SchM_Exit_Rte(RTE_EXCLUSIVE_AREA_0);

/* ---------------------------
   4. RTE Exclusive Area終了
   --------------------------- */
Rte_Exit_Rte(RTE_EXCLUSIVE_AREA_0);

}
c) 補足: 関数の呼び出し関係
Rte_Enter_Rte() → 内部で SchM_Enter_Rte()
Rte_Exit_Rte() → 内部で SchM_Exit_Rte()
つまり、SWCがRTEのバッファや共有リソースにアクセスする際は RTEレベルでEnter/Exitを呼ぶ。
さらに、RTE内部でOS保護が必要な場合は SchMで低レベル排他制御 を行う構造です。
Rte_Start() はタスクやタイマーを起動してRunnableを実行可能にする
Rte_Stop() はタスク・タイマーを停止してRTEを停止
d) 図で表すと
main()
└─> Rte_Start()
└─> OSタスク起動
└─> EngineControl_MainFunction()
├─> Rte_Enter_Rte()
│ └─> SchM_Enter_Rte()
├─> データ読み書き
├─> SchM_Exit_Rte()
└─> Rte_Exit_Rte()
💡 まとめ
Rte_Start / Rte_Stop → RTE全体の起動・停止
Rte_Enter / Rte_Exit → SWCから見たRTEの排他制御
SchM_Enter / SchM_Exit → RTE内部やBSWモジュールの低レベル排他制御
SWCのRunnableは Rte_Enter/Exitで囲み、必要に応じて内部でSchMも使う
希望であれば、この関係を PlantUMLでタスク・RTE・SchMの排他フロー図 にして可視化することもできます。
作りますか?

はい。

了解です。では、AUTOSARの タスク → RTE → SchM → SWC → BSW の排他制御フローをPlantUMLで図解します。Rte_Enter / Rte_Exit と SchM_Enter / SchM_Exit の関係も可視化します。
@startuml
title AUTOSAR RTE / SchM 排他制御フロー

actor "Main Function" as Main
participant "RTE_Start()" as RTEStart
participant "OS Task" as OSTask
participant "SWC Runnable" as SWCRunnable
participant "RTE_Enter / Exit" as RTEEnterExit
participant "SchM_Enter / Exit" as SchMEnterExit
participant "BSW Module / Shared Resource" as BSW

== システム起動 ==
Main -> RTEStart : Rte_Start()
RTEStart -> OSTask : タスク・タイマー起動

== タスク実行 ==
OSTask -> SWCRunnable : Runnable起動

== RTE排他開始 ==
SWCRunnable -> RTEEnterExit : Rte_Enter_Rte()
RTEEnterExit -> SchMEnterExit : SchM_Enter_Rte() (低レベル排他)

== データアクセス ==
SWCRunnable -> BSW : 共有リソースアクセス
BSW --> SWCRunnable : データ返却

== 排他終了 ==
SWCRunnable -> SchMEnterExit : SchM_Exit_Rte()
SWCRunnable -> RTEEnterExit : Rte_Exit_Rte()

== 次の周期・イベント ==
OSTask --> SWCRunnable : Runnable再呼び出し
@enduml
図の解説
Rte_Start()
OSタスクやタイマーを起動してSWC Runnableの実行を可能にする
OS Task
周期タスクやイベント駆動タスクとしてRunnableを呼び出す
Rte_Enter / Rte_Exit
SWCがRTEバッファや内部データを安全に扱うための排他制御
SchM_Enter / SchM_Exit
RTE内部やBSWモジュールの低レベル共有リソース排他
OS割り込み停止やネスト可能カウンタで管理
BSW Module / Shared Resource
CANバッファやADCデータなど、共有ハードウェアリソース
この図を見ると、SWCはRTEを通してSchMの排他制御を使い、共有リソースへの安全なアクセスが保証されることが一目でわかります。
必要であれば、次のステップとして Rte_Stop() まで含めた完全ライフサイクル図 も作れます。作りますか?

rte_start, rte_stopがなくてもビルドできるとお聞きしました。本当でしょうか。

はい、それは 本当です。ただし条件があります。順を追って整理します。

  1. Rte_Start / Rte_Stop の役割
    Rte_Start()
    RTE内部でOSタスクやタイマーを起動
    Runnableを周期的・イベント駆動で呼ぶための準備
    Rte_Stop()
    RTEのタスクやタイマーを停止
    システムシャットダウンやリソース解放用

  2. ビルド可能かどうか
    ビルド(コンパイル/リンク)自体は可能
    Rte_Start / Rte_Stop は単なる関数なので、呼ばなくてもCコードはコンパイルできます
    実際にビルドエラーになるわけではありません
    ただし実行時には影響がある
    Rte_Start を呼ばない場合、OSタスクやタイマーが起動しないため、Runnableが自動で呼ばれません
    手動でRunnableを呼ぶ場合は問題なく動作可能

  3. 典型的な例
    a) Rte_Start を呼ぶ場合
    int main(void)
    {
    Rte_Init();
    Rte_Start(); // OSタスクやタイマーを起動
    while(1) { /* OSスケジューラがRunnableを周期実行 */ }
    }
    b) Rte_Start を呼ばない場合(手動呼び出し)
    int main(void)
    {
    Rte_Init();

    /* Runnableを手動で呼ぶ */
    while(1) {
    EngineControl_MainFunction();
    ThrottleMonitor_MainFunction();
    }
    }
    この場合、OSタスクやタイマーは不要
    ビルドも問題なし
    しかし、AUTOSAR標準のタスクスケジューリング機能は使えない

  4. まとめ
    ビルドは可能:Rte_Start / Rte_Stop を呼ばなくてもCコードはコンパイル可能
    実行上の違い:
    Rte_Start を呼ぶ → OSタスク・タイマーで自動呼び出し
    呼ばない → Runnableは手動で呼ぶ必要がある
    通常は自動スケジューリングのために呼ぶのが標準的
    💡 要点:Rte_Start / Rte_Stop は必須ではないが、AUTOSAR準拠の自動スケジューリングには必須というイメージです。
    もしよければ、Rte_Start なしで手動呼び出しした場合の RTE / SchM の排他フロー図もPlantUMLで示せます。作りますか?

rte_start以外の関数からOSタスク・タイマーを自動呼び出しできませんか?

結論から言うと、標準のAUTOSAR RTEでは、Rte_Start() を呼ばない限り OSタスク・タイマーは自動的に起動されません。
ただし、工夫すれば「Rte_Start 以外の関数」から間接的に起動することは可能です。順を追って説明します。

  1. なぜ Rte_Start() が必要か
    Rte_Start() は、RTEが管理する周期タスクやイベント駆動タスクの登録・起動を行う関数です。
    AUTOSAR RTEの生成コードでは、OSタスクやOSカウンタ、OSアラームなどを Rte_Start() 内で初期化・起動 します。
    そのため、Rte_Start() を呼ばなければ、RunnableはOSのスケジューラから自動的には呼ばれません。
  2. 代替手段
    a) 手動でOSタスクやタイマーを起動する
    Rte_Start() が内部で呼んでいる処理を自分で呼び出すことが可能
    例: OSの ActivateTask や SetRelAlarm を直接呼ぶ
    #include "Os.h"

/* Rte_Start() と同等の処理 /
void My_Rte_Start_Alternative(void)
{
/
OSアラーム設定で周期タスクを起動 */
SetRelAlarm(EngineControlTaskAlarm, 10, 10); // 10ms周期
SetRelAlarm(ThrottleMonitorTaskAlarm, 5, 5); // 5ms周期
}
この関数を main() などから呼べば、Rte_Start() を使わずにOSタスクを起動可能
b) Runnableを直接OSタスクに登録する(コード生成時の調整)
AUTOSARツールの生成設定で、RTE_TaskActivationをカスタマイズ
タスク開始関数を独自関数に差し替えることで、Rte_Start() を不要にする
c) 完全手動呼び出し
OSやタイマーを使わず、mainループでRunnableを直接呼ぶ
int main(void)
{
Rte_Init();

while(1)
{
    EngineControl_MainFunction();
    ThrottleMonitor_MainFunction();
}

}
実行は可能だが、周期精度やスケジューリングは自分で管理する必要がある
3. 注意点
AUTOSAR標準準拠では推奨されない
Rte_Start() を呼ばないと、OSのタイマーイベントやアラームなどの機能が正しく使えない
代替方法は「軽量RTE」や「単体テスト用」として使うケースが多い
💡 まとめ
方法 メリット デメリット
Rte_Start() を使う 標準準拠、OSタスク/アラーム自動起動 なし
OS APIを直接呼ぶ Rte_Start不要で自動起動可能 AUTOSAR準拠でない、保守性低
Runnableを手動呼び出し 最も単純 スケジューリング管理が必要、周期精度が保証されない
希望であれば、Rte_StartなしでOSタスクやタイマーを自動呼び出す場合のPlantUMLフロー図も作れます。
作りますか?

なるべくモジュールを小さくして速くするために、省略していい関数の例を16個示してくだし。

わかりました。AUTOSAR RTE / BSW を最小化・高速化する目的で、省略可能(使わない場合でもビルド可能)な関数・APIの例を、代表的なものを 16個 挙げます。
※「省略可能」はシステム構成や使用モジュールによります。必ずしも全てのプロジェクトで省略可能ではありません。

  1. RTE関連
    No 関数 省略理由 / 補足
    1 Rte_Start() OSタスク・タイマーを使わず、手動呼び出しでRunnableを実行する場合
    2 Rte_Stop() システム終了をRTEが管理しない場合
    3 Rte_Enter_() クリティカルセクション不要な単純SWCの場合
    4 Rte_Exit_() 同上
    5 Rte_Init() SWCが内部データ初期化不要で直接値を設定する場合
    6 Rte_IrvRead_() Inter-Runnable Variable を使わない場合
    7 Rte_IrvWrite_() 同上
    8 Rte_Call_() Client/Server通信を使わないSWCの場合
  2. SchM関連(Exclusive Area管理)
    No 関数 省略理由 / 補足
    9 SchM_Enter_() 共有リソースや割り込み保護が不要な場合
    10 SchM_Exit_() 同上
    11 SchM_Enter_Nested() ネスト可能なクリティカルセクションを使わない場合
    12 SchM_Exit
    _Nested() 同上
  3. BSW / COM / CAN など
    No 関数 省略理由 / 補足
    13 Com_SendSignal() 信号送信機能を使わない場合
    14 Com_ReceiveSignal() 信号受信機能を使わない場合
    15 Can_Write() CAN送信を使用しない場合
    16 Can_Read() CAN受信を使用しない場合
    💡 ポイント
    排他制御や通信APIは不要なら省略可能
    シンプルなSWCやテスト用RTEで有効
    Rte_Start / Stop を省略するとOSの周期タスク管理は自分で行う必要あり
    ビルド可能かどうかは、実際に生成されたRTE/BSWコードの依存関係に左右される
    最適化の基本: 使わないモジュール・ポート・Runnable・通信・排他制御を生成しない設定にする
    希望であれば、この「省略可能関数16個」を RTE/SchM/BSWフローのPlantUML図上で省略部分を赤字で示す 形で可視化することもできます。
    作りますか?

zero copyの考え方にしたがい、なるべくバッファを持たないようにするには、どういう関数が不要ですか。

なるほど。「Zero Copy」の考え方で、なるべく バッファを持たずにデータを直接渡す 方式にするときに 不要になる関数・API を整理します。AUTOSAR RTE / BSWを前提に考えます。

  1. Zero Copy の基本
    データを RTE内部やCOMバッファにコピーせず、参照で渡す
    バッファコピーを伴う API は不要になる
    目的: メモリ使用量削減・レイテンシ短縮・高速化
  2. 不要になる典型的関数
    a) RTE バッファ関連
    No 関数 理由
    1 Rte_IrvWrite_() Inter-Runnable Variable にコピーする必要がなくなる
    2 Rte_IrvRead_() コピーせず参照で取得できれば不要
    3 Rte_Write_() Sender Port バッファにコピーせず直接参照渡しが可能
    4 Rte_Read_() Receiver Port のコピー読み出しは不要
    5 Rte_Send_() イベントに伴う内部バッファやキューを使わない場合
    6 Rte_Receive_() 同上
    b) BSW / COM バッファ関連
    No 関数 理由
    7 Com_SendSignal() バッファにコピーして送信する場合は不要、直接参照送信可能
    8 Com_ReceiveSignal() バッファコピー不要、受信データを参照で渡せば不要
    9 Can_Write() CANデータコピー不要なら直接送信
    10 Can_Read() 受信バッファコピー不要、参照渡しのみ
    c) SchM / クリティカルセクション関連
    バッファアクセスを伴う排他制御は不要になることがある
    No 関数 理由
    11 SchM_Enter_() バッファ保護不要なら省略可能
    12 SchM_Exit_() 同上
    d) RTE タイマー/キュー関連
    No 関数 理由
    13 Rte_SetEvent() キューにデータをコピーするイベント通知不要
    14 Rte_WaitEvent() コピー不要なら、参照で直接Runnable起動
    15 Rte_QueueWrite() 内部キューにコピー不要
    16 Rte_QueueRead() 内部キューコピー不要
  3. まとめ
    Zero Copy 化の基本方針: 「コピーを伴う関数・バッファを使わない」
    省略可能関数は主に RTEバッファ操作系、COM/CANバッファ操作系、イベントキュー系
    SchMの排他も、バッファ保護が不要なら省略可能
    メリット: メモリ消費減、処理遅延減
    デメリット: データ整合性や競合に注意が必要(参照で共有するため)
    💡 もし希望なら、この Zero Copy化で不要になる関数16個 を RTE / SchM / BSWフロー図に赤で省略表示 してPlantUMLで可視化することもできます。
    作りますか?

はい。

わかりました。では、Zero Copy化の考え方に基づき、バッファを持たずに直接参照でデータを渡す場合に不要になる関数を、RTE / SchM / BSWフロー図としてPlantUMLで可視化します。
@startuml
title Zero Copy時に不要となるRTE/SchM/BSW関数

actor "Main Function" as Main
participant "RTE_Start()" as RTEStart
participant "OS Task" as OSTask
participant "SWC Runnable" as SWCRunnable
participant "RTE (バッファ)" as RTEBuffer
participant "SchM (排他)" as SchM
participant "BSW/COM/CAN" as BSW

== システム起動 ==
Main -> RTEStart : Rte_Start() (必要)

== タスク実行 ==
OSTask -> SWCRunnable : Runnable起動

== バッファコピー不要(Zero Copy) ==
SWCRunnable -> RTEBuffer : ~Rte_Write_()~
SWCRunnable -> RTEBuffer : ~Rte_Read_()~
SWCRunnable -> RTEBuffer : ~Rte_IrvWrite_()~
SWCRunnable -> RTEBuffer : ~Rte_IrvRead_()~
SWCRunnable -> RTEBuffer : ~Rte_Send_()~
SWCRunnable -> RTEBuffer : ~Rte_Receive_()~
SWCRunnable -> BSW : ~Com_SendSignal()~
SWCRunnable -> BSW : ~Com_ReceiveSignal()~
SWCRunnable -> BSW : ~Can_Write()~
SWCRunnable -> BSW : ~Can_Read()~
SWCRunnable -> SchM : ~SchM_Enter_()~
SWCRunnable -> SchM : ~SchM_Exit_()~
SWCRunnable -> RTEBuffer : ~Rte_SetEvent()~
SWCRunnable -> RTEBuffer : ~Rte_WaitEvent()~
SWCRunnable -> RTEBuffer : ~Rte_QueueWrite()~
SWCRunnable -> RTEBuffer : ~Rte_QueueRead()~

== 実データアクセス(参照渡し) ==
SWCRunnable -> BSW : データ参照で直接アクセス

@enduml
図の解説
赤字/取り消し線 (~ ~) で示した関数は Zero Copy化により不要
SWC Runnable は 参照で直接データにアクセスする
SchMの排他も、共有バッファがない場合は不要
Rte_Start() は依然として OSタスクやタイマーを起動するために必要
💡 この図をもとに、Zero Copy設計では コピー用APIやバッファ・キュー・イベント処理の大半を省略できることが視覚的に理解できます。
必要であれば、Zero Copy化前後でのメモリ使用量・コピー回数の比較図 も作ることが可能です。作りますか?

はい。

了解です。では、Zero Copy化の前後で メモリ使用量とコピー回数 を比較したPlantUMLフロー図を作ります。
@startuml
title Zero Copy 前後の比較(メモリ使用量・コピー回数)

actor "SWC Runnable" as SWC

package "従来方式 (コピーあり)" {
participant "RTE バッファ" as RTEBuffer
participant "BSW/COM/CAN" as BSW

SWC -> RTEBuffer : データを書き込み(コピー1回)
SWC <- RTEBuffer : データを読み込み(コピー2回)
SWC -> BSW : 信号送信(コピー3回)
SWC <- BSW : 信号受信(コピー4回)

}

note right of RTEBuffer
メモリ使用量:

  • ポートバッファ
  • IRVバッファ
  • イベント/キュー
    コピー回数: 4回
    end note

package "Zero Copy 方式" {
participant "直接参照" as DirectRef
participant "BSW/COM/CAN" as BSW2

SWC -> DirectRef : データ参照渡し(コピー0回)
SWC -> BSW2 : データ参照渡し(コピー0回)

}

note right of DirectRef
メモリ使用量:

  • バッファ不要
    コピー回数: 0回
    end note

@enduml
図の解説
従来方式 (コピーあり)
RTEバッファやIRV(Inter-Runnable Variable)、COM/CANバッファにコピー
コピー回数が増える → メモリ使用量増、処理遅延増
Zero Copy方式
データは参照で直接アクセス
バッファ不要 → メモリ削減
コピー回数 0 → 高速化
💡 この図で Zero Copy化のメリット が一目でわかります:
メモリ消費削減
コピー回数ゼロ → レイテンシ低減
SchMやRTEのバッファ関連関数を省略可能
希望であれば、次に Zero Copy設計時に残す必要のある最低限のRTE/SchM関数のみを赤字で表示したフロー図 も作れます。作りますか?

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?