文章

ETAS的PHM问题研究

相关项目

AraPHM_Example是ETAS提供的官方示例。在ETAS文档中也有对此项目进行详细的说明。下面的内容来至ETAS提供的Example文档。

ETAS对AraPHM_Example的说明

image1 一个自适应应用程序,展示了以下监督机制的使用:

  • 期限监督(Deadline Supervision):一种机制,用于检查从“期限开始检查点”到对应的“期限结束检查点”的过渡执行时间是否在配置的最小和最大限制范围内。
  • 存活监督(Alive Supervision):一种机制,用于检查周期性被监督实体的时间约束是否在配置的最小和最大限制范围内。
  • 逻辑监督(Logical Supervision):一种机制,用于检查被监督实体(或一组被监督实体)是否按照配置的预期顺序执行。

该应用程序还展示了被监督实体的检查点配置及其他监督属性的设置。

AraPHM_Example 示例使用 ara::log 将结果输出到控制台。 若要使用 RTA-VRTE Starter Kit 附带的 DLT Viewer 查看和过滤输出日志消息,请将 ECU 连接到 ECU1,并为目标 ECU 设置正确的 IP 地址,同时将 ara::log 的配置从控制台模式修改为远程模式。有关 DLT Viewer 的使用详情,请参阅 RTA-VRTE Starter Kit V3.4.0 用户指南 [3]。 或者,您可以将 PhmDlt.dlp 作为项目在 DLT Viewer 中打开。此项目包含一些过滤器,可帮助您区分示例中的各个进程。

[!WARNING]

PHM 和 LOG 使用与时间相关的特性,因此日志消息的顺序可能会因机器(或虚拟机)以及 POSIX 操作系统的差异而有所不同。

AraPHM_Example 示例包含八个被监督实体(se0, se2, se3, se4, se5, se6, se7, 和 se8),这些实体根据其检查点进行了配置(可在以 “phm_” 开头的 ARXML 文件夹中查看配置)。根据这些配置,头文件(se0.h, se2.h, se3.h, se4.h, se5.h, se6.h, se7.h, se8.h)将生成在 /gen/ara/phm/supervised_entities 文件夹中。

被监督实体(SE)接口的配置是通过 AR Explorer 工具完成的。以下文件包含了示例应用程序中使用的监督配置定义:

  • PHMContributions_Tests_Supervision_Deadline.arxml 包含期限(Deadline)配置的定义。
  • PHMContributions_BinaryTests_Supervision_Alive.arxml 包含存活(Alive)配置的定义。
  • PHMContributions_BinaryTests_Supervision_Logical.arxml 包含逻辑(Logical)配置的定义。
  • PHMContributions_BinaryTests_Supervision_Mixed.arxml 包含期限(Deadline)和逻辑(Logical)配置的定义。

一旦 AraPHM_Example 示例应用程序被编译和构建,将生成以下二进制文件。每个二进制文件展示了不同的用例:

  • phm_se2Timeout

    演示了期限监督(Deadline Supervision)的失败情况,因为目标检查点未在配置的最大期限内报告。 该过渡的期限范围为 [9ms, 17ms]

    在软件中,从 Initial CheckpointFinal Checkpoint 的过渡时间定义为 20ms

    由于 Final Checkpoint 超过了配置的最大期限后才被报告,因此应记录一条包含“Local Supervision switched to Expired”(本地监督切换到过期)的期限监督错误消息。

    image2

[!NOTE]

这里只给出了phm_se2Timeout的说明,因为只有phm_se2Timeout才会触发Recovery Action。

Example的编译、运行

目前,AraPHM_Example不能直接编译运行,在文档中只给出的编译运行命令是QNX的,需要对原本AraPHM_Example做部分修改。

  1. 在software cluster中删除rb-watchdog的引用

    image3

此时,程序就可以正常运行了。但是在运行到phm_se2Process的时候,不会出现Recovery Action的日志。

使用

1
rvbuild -d AraPHM_Example 20

编译以及运行程序

image4

从上截图可以看到,没有Recovery Action相关的log。

  1. 在PHM编辑器中,创建一个Recovery Action。

    image5

    image6

[!NOTE]

创建Recovery Action的方法可以参考RTA-VRTE v3.4.0 User Guide的553页的Recovery Notification章节。

再次编译运行得到以下结果:

image7

ETAS对此问题的说明

image8

翻译如下:

恢复通知未被传输 描述:如果请求恢复操作,会出现以下错误:Creation of FunctionGroup failed with reason Wrong meta model identifier passed to a function.(创建功能组 (FunctionGroup) 失败,原因是传递给函数的元模型标识符 (meta model identifier) 错误。) 对系统的影响:恢复操作功能不可用。 解决方法:欲了解更多信息,请联系 ETAS,详见第 20 节。

对此问题的调查

尝试反编译librb-phm-recovery-notification.so库,得到librb-phm-recovery-notification.so.c文件。在文件中搜索Recovery Notification,找到了如下:

image9

可以看到和错误提示的前半部分完全相同。

那么Wrong meta model identifier passed to a function错误是哪里来的呢?在上面调用了ara::exec::FunctionGroup::Create函数,而此函数就会导致此错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    /**
    * @brief Named constructor for FunctionGroup. This method shall validate/verify meta-model path passed and perform FunctionGroup object
    creation.

    * @param metaModelIdentifier stringified meta model identifier (short name path) where path separator is '/'.
    * @returns an instance of FunctionGroup, or ExecErrc error
    * @error ara::exec::ExecErrc::kMetaModelError if metaModelIdentifier passed is incorrect (e.g. FunctionGroupState identifier has been
    passed).
    * @error ara::exec::ExecErrc::kGeneralError if any other error occurs.
    * @threadsafety{Thread-safe}

    * @traceid{SWS_EM_02323}@tracestatus{draft}
    * @uptrace{RS_EM_00101}
    */
    static ara::core::Result<FunctionGroup> Create(ara::core::StringView metaModelIdentifier) noexcept;

如果metaModelIdentifier错误,会得到ara::exec::ExecErrc::kMetaModelError错误。而KmetaModelError就会导致出现此错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
inline char const* ExecErrorDomain::Message(const CodeType errorCode) const noexcept
{
#if defined(__GNUC__)
    /* RULECHECKER_comment(1, 2, check_pragma_usage, "External tooling requires pragma.", true); */
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
    ara::exec::ExecErrc const code = static_cast<ara::exec::ExecErrc>(
            errorCode); // PRQA S 3013 #The function argument is of type uint32_t so it has to be cast to an enum for further evaluation
    switch (code)
    {
        case ara::exec::ExecErrc::kGeneralError:
        {
            return "Some unspecified error occurred";
        }
        case ara::exec::ExecErrc::kInvalidArguments:
        {
            return "Invalid argument was passed";
        }
        case ara::exec::ExecErrc::kCommunicationError:
        {
            return "Communication error occurred";
        }
        case ara::exec::ExecErrc::kMetaModelError:
        {
            return "Wrong meta model identifier passed to a function"; // 和log输出的一模一样
        }

从上述可以得知,是因为metaModelIdentifier错误。在AraPHM_Example的gen目录查找metaModelIdentifier,得到

image10

可以看出,可能是/FunctionGroupSets/FunctionGroupSet_0/MachineFG导致的。尝试手动使用ara::exec::FunctionGroup::Create函数调用此functionGroupMetaModelIdentifier。

1
2
3
4
5
6
auto res = ara::exec::FunctionGroup::Create("/FunctionGroupSets/FunctionGroupSet_0/MachineFG");
if (res.HasValue()) {
    Log.LogInfo() << "1111111111111111111111111111111111111111111111111";
} else {
    Log.LogInfo() << "2222222222222222222222222222222: " << res.Error().Message();
}

编译、运行得到

image11

可以看到出现了同样的错误。就是生成的PHM配置文件中functionGroupMetaModelIdentifier错误导致的。那么正确的functionGroupMetaModelIdentifier是什么呢?

1
2
3
4
5
6
auto res = ara::exec::FunctionGroup::Create("/ModeDeclarationGroups/MachineFG");
if (res.HasValue()) {
    Log.LogInfo() << "1111111111111111111111111111111111111111111111111";
} else {
    Log.LogInfo() << "2222222222222222222222222222222: " << res.Error().Message();
}

这里的/ModeDeclarationGroups/MachineFG就是实际MachineFG的路径,不是上面的FunctionGroupSet。

尝试编译运行得到

image12

那么,/ModeDeclarationGroups/MachineFG就是正确的functionGroupMetaModelIdentifier

解决思路

解决方法一

解决方案:

将生成的配置文件中的functionGroupMetaModelIdentifier改为正确的内容

结论:

不可行,ETAS AP运行的时候,实际是使用的是xxx.bin,而不是xxx.json。

[!NOTE]

尝试过手动修改xxx.bin里的functionGroupMetaModelIdentifier,etas ap程序直接不能运行。

解决方法二

解决方案:

将arxml中的FunctionGroupSet和ModeDeclarationGroups配置成相同的

结论:

不可行,这样会有冲突。

解决方法三

解决方案:

  1. 首先将生成的配置文件中的functionGroupMetaModelIdentifier改为正确的内容。

  2. 使用flatc命令将配置文件转换成xxx.bin。例如:

    1
    
    /usr/local/etas/vrte/flatc/flatc  -b -c -o ./out gen/phm_flatcfg.fbs gen/softwarecluster_0/phm__SoftwareCluster_0_flatcfg.json
    
  3. 将生成的xxx.bin替换原来的bin文件

对于AraPHM_Example,具体需要修改gen/softwarecluster_0/phm__SoftwareCluster_0_flatcfg.json文件,修改如下:

image13

最后需要将生成的phm__SoftwareCluster_0_flatcfg.bin拷贝至/opt/vrte/saf-aap-platform-health-management/etc/ecu-cfg下。

结论:

可行。

最终解决方案

修改/usr/local/etas/vrte/vrte_fs/ecucfgdsl/PHM.ecucfgdsl文件。1996行的函数getModeDeclarationGroup存在错误。

1
2
3
4
5
6
// Get Mode Declaration Group.
// [in] checkpoint  Autosar SupervisionCheckpoint
// return           Mode Declaration Group Autosar Path as string
function getModeDeclarationGroup(SupervisionCheckpoint checkpoint) : string {
	return checkpoint.process.stateDependentStartupConfigs.functionGroupStates.contextModeDeclarationGroupPrototype[0].arpath()
}

checkpoint.process.stateDependentStartupConfigs.functionGroupStates.contextModeDeclarationGroupPrototype[0].type.arpath()的结果其实是FunctionGroupSet的路径。如果要获取getModeDeclarationGroup的路径,需要修改成如下:

1
2
3
4
5
6
// Get Mode Declaration Group.
// [in] checkpoint  Autosar SupervisionCheckpoint
// return           Mode Declaration Group Autosar Path as string
function getModeDeclarationGroup(SupervisionCheckpoint checkpoint) : string {
    return checkpoint.process.stateDependentStartupConfigs.functionGroupStates.contextModeDeclarationGroupPrototype[0].type.arpath()
}

在原本最后的.arpath()前加上.type即可。

本文由作者按照 CC BY 4.0 进行授权