附录 E - ThreadX SMP MISRA C 合规性

MISRA C 概述

MISRA C 是一组编程准则,面向使用 C 编程语言的关键系统。 最初的 MISRA C 准则主要面向汽车业应用;但是,现在人们广泛认可 MISRA C 适用于任何安全关键应用。 MISRA-C:2004 包含 142 条规则(其中有 122 条是必需的,有 20 条是建议性的)。 MISRA C:2012 包含 143 条重要程度各不相同的规则和 16 条指令。 ThreadX 符合 MISRA-C:2004 和 MISRA C:2012 的所有“必需”规则和“强制性”规则。 ThreadX 还符合所有规则(两条建议性规则除外)。

ThreadX SMP 具有几乎相同的合规性,但有两条“必需”规则除外,这两条规则是特定于 ThreadX SMP 实现的。 这些规则的优先级较低,是重用标准 ThreadX 代码库所必需的。

实现 ThreadX SMP MISRA 合规性

通过构建 ThreadX SMP 库并定义 TX_MISRA_ENABLE,实现 MISRA 完全合规性

需要注意的是,TX_MISRA_ENABLE 必须在命令行或 IDE 的项目设置中进行定义,也就是说,仅在 tx_port.h 或 tx_user.h 中进行定义是不够的。 所有其他定义都可添加到头文件中。 此外,不得定义 TX_INLINE_INITIALIZATION。 默认情况下,此内容在大多数分发的 tx_port.h 文件中进行定义

注意

某些版本的 ThreadX SMP 可能需要更改项目和/或 。 有关其他信息,请参阅本文档末尾的内容。

MISRA 合规性概览

MISRA C:2012 中有几个区域不容易通过静态分析工具(例如 IAR 的 C-STAT)确定。 本部分将介绍这些方面,如下所示:

Directive

ThreadX SMP 合规性支持

Dir 1.1

IEC 61508 认证表明符合此指令。

Dir 3.1

IEC 61508 认证表明符合此指令。

Dir 4.1

IEC 61508 认证表明符合此指令。

Dir 4.2

有 8 个汇编语言文件(每个文件的大小实际上都是一个函数)包含一个典型的 ThreadX SMP 端口。 程序集文件包括:
txinitialize_low_level.s
txthread_context_save.s
txthread_context_restore.s
txthread_interrupt_control.s
txthread_schedule.s
txthread_smp_core_get.s
txthread_smp_core_preempt.s
txthread_smp_current_state_get.s
txthread_smp_current_thread_get.s
txthread_smp_initialize_wait.s
txthread_smp_low_level_initialize.s
txthread_smp_protect.s
txthread_smp_time_get.s
txthread_smp_unprotect.s
txthread_stack_build.s
txthread_system_return.s
txtimer_interrupt.s
当 TX_MISRA_ENABLE 用于生成 ThreadX SMP 库时,会出现另一个程序集文件 tx_misra.s,该文件封装了所有指针算术/操作。

ThreadX SMP MISRA 例外情况

ThreadX SMP 符合几乎所有“必需”和“强制”的 MISRA-C:2004 和 MISRA C:2012 规则/指令。 唯一的例外是几条“建议性”和“低优先级”的必需规则/指令,如下所示:

MISRA 例外情况:

MISRA-C:2004 5.6(建议性)
MISRA C:2012 Dir 4.5(建议性)

“一个命名空间中的标识符不应与另一个命名空间中的标识符具有相同的拼写,但结构成员和联合成员名称除外。”

有少数与通知回调关联的结构成员名称在它们的前 31 个字符中是相同的。 此外,还有一些宏参数在此指令方面存在问题。

MISRA C:2012 Dir 5.1 (所需)

“外部标识符应是不同的。这是链接分析检查。

几个全局变量的前 31 个字符是相同的。

MISRA-C:2004 16.7(建议性)

“如果指针不用于修改寻址对象,则函数原型中的指针参数应声明为指向 const 的指针。”

ThreadX SMP 在此 MISRA 规则之前已建立 API,因此在 ThreadX SMP API 中更改此 API 是不切实际的。 此外,ThreadX SMP 中的某些服务是有条件地启用或禁用的,因此在某些情况下,提供的指向 API 的指针不用于修改寻址对象。

MISRA-C:2004 19.7(建议性)
MISRA C:2012 4.9(建议性)

“应优先使用函数而不是类似函数的宏。”

ThreadX SMP 使用类似函数的宏来使 ThreadX SMP 代码库在 ThreadX SMP 支持的许多不同处理器之间更具可移植性。

MISRA C:2012 Dir-4.6_b(建议性)

“应使用指示大小和符号的 typedef 来代替基本的数字类型。”

ThreadX SMP 使用不带符号或大小信息的基本 typedef,例如 UINT 和 ULONG。

MISRA C:2012 Dir-4.8(建议性)

“如果指向结构或联合的指针永远不会在翻译单元中取消引用,则应隐藏对象的实现。”

ThreadX SMP 对象具有结构名称和 typedef 名称。 由于 ThreadX SMP 代码不直接使用结构名称,因此不满足此建议性指令。

MISRA C:2012 2.3(建议性)

“项目不应包含未使用的类型声明。”

ThreadX SMP 定义了一些不在标准 ThreadX SMP 配置中使用,但在某些配置和 ThreadX SMP 支持的中间件中使用的 typedef。

MISRA C:2012 2.4(建议性)

“项目不应包含未使用的标签声明。”

在定义 typedef 时,ThreadX SMP 仅使用某些结构一次。

MISRA C:2012 2.5(建议性)

“项目不应包含未使用的宏声明。”

ThreadX SMP 定义了一些不在标准 ThreadX SMP 配置中使用,但在某些配置和 ThreadX SMP 支持的中间件中使用的 typedef。

MISRA C:2012 2.7(建议性)

“函数中不应有未使用的参数。”

默认情况下,ThreadX SMP 符合此建议性规则。 但当使用 TX_DISABLE_NOTIFY_CALLBACKS 生成 ThreadX 时,ThreadX SMP 库中的 4 个函数将被标记为不满足此建议性规则,如下所示

tx_event_flags_set_notify.c
tx_queue_send_notify.c
tx_semaphore_put_notify.c
tx_thread_entry_exit_notify.c

此外,定义 TX_TIMER_PROCESS_IN_ISR 时,tx_timer_thread_entry.c 文件将被标记为不满足此建议性规则

需要 MISRA C:2012 3.1 ()

“字符序列 /* 和 // 不得在注释中使用。”

“//”在 Microsoft 版权中用作 URL 的一部分。

MISRA C:2012 8.7(建议性)

“如果仅在一个翻译单元中引用函数和对象,则不应使用外部链接来定义它们。”

ThreadX SMP 中的内部函数和变量并不总是被多个外部翻译单元引用。

MISRA C:2012 8.9_b(建议性)

“如果对象的标识符仅出现在单个函数中,则应在块范围内定义对象。”

ThreadX SMP 的一些全局数据元素仅在一个函数中引用,因此,这条规则有例外情况。

MISRA C:2012 8.13(建议性)

“指针应尽可能指向 const 限定类型。”

ThreadX SMP API 具有未修改的输入参数,但指针没有 const 限定符。

MISRA C:2012 17.8(建议性)

“不应修改函数参数。”

在几个文件中,ThreadX SMP API 的输入参数被用作 API 本身的局部变量。 没有副作用,因为 C 中的参数作为值传递。

MISRA-C:2004 20.1(必需但优先级低)
MISRA C:2012 21.1

“不应定义、重新定义或未定义标准库中的保留标识符、宏和函数”

ThreadX SMP 利用许多经过现场验证的 ThreadX 单核心源代码。 但为了实现重用,宏用于将特定于每个核心的数据结构替换为函数调用或由核心编制索引的数组,如下所示:

按核心编制索引的数组

从技术上说,这不会替换保留标识符,但 MISRA-C:2004 规范指示不能重新定义带下划线的项。

MISRA C:2012 5.2(必需但优先级低)

“在同一范围和名称空间中声明的标识符应不同”

这种情况与上一个问题相同,“_tx_thread_system_state”的宏重新定义与实际数据结构的默认定义匹配,这是预期情况,因为 ThreadX SMP 需要替代标准的单核心数据结构用法

MISRA C:2012 18.1(必需)

“基于指针操作数的算术生成的指针应处理与指针操作数相同的数组的元素。”

C-STAT 在生成线程 SMP 库时会生成 6 条消息,但这些消息都是误报,即此版本的 C-STAT 会错误地报告此错误。

MISRA C 验证工具

使用 IAR EWARM 8.11.1 C-STAT 1.4.4 MISRA-C:2004 和 MISRA C:2012 验证 ThreadX SMP MISRA 合规性。 下图显示了 C-STAT 检查的 MISRA C 规则(并且还充当合规性矩阵):

IAR EWARM 8.11.1C-STAT 1.4.4MISRA-C:2004MISRA C:2012

图 1:MISRA-C:2004/MISRA C:2012 合规性矩阵

在没有 TX_MISRA_ENABLE 的情况下生成 ThreadX SMP

在没有 TX_MISRA_ENABLE 的情况下生成 ThreadX SMP 具有显著的运行时性能优势,并且是 ThreadX SMP 的默认(推荐)配置。 以此方式生成时,无法满足以下几条MISRA C 强制性规则:

MISRA-C:2004

MISRA C:2012

8.5a、10.1a、11.3、12.13、13.2d、14.7、17.4a

10.3、11.4、13.3、14.4d、15.5、17.7

其他项目和/或 tx_port.h 要求

某些版本的 ThreadX SMP 可能需要其他配置才能完全符合 MISRA。 除使用 TX_MISRA_ENABLE 生成 ThreadX SMP 外,ThreadX 项目还应指定 C 方言 C89 并选择严格的语言合规性,如下所示

严格语言一致性

其次,如果 ThreadX 版本没有预建的 tx_misra.s 程序集文件,则 tx_misra.c 文件应编译为程序集,并且程序集文件应包含在项目中

最后,tx_port.h 应进行以下更改,以实现 MISRA 完全合规性

  1. 以下定义应显示在 tx_port.h 或项目设置中

    #define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
    #define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
    #define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
    #define TX_MUTEX_ENABLE_PERFORMANCE_INFO
    #define TX_QUEUE_ENABLE_PERFORMANCE_INFO
    #define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
    #define TX_THREAD_ENABLE_PERFORMANCE_INFO
    #define TX_TIMER_ENABLE_PERFORMANCE_INFO

  2. 不应在 tx_port.h 或项目设置中定义 TX_DISABLE_NOTIFY_CALLBACKS

  3. 应定义 TX_DISABLE_INLINE 以禁用 ThreadX SMP 中的内嵌帮助程序函数。

  4. 应重新定义跟踪计时器源,如下所示:

    #ifndef TX_MISRA_ENABLE
    #ifndef TX_TRACE_TIME_SOURCE
    #define TX_TRACE_TIME_SOURCE /* ORIGINAL SOURCE */
    #endif
    #else
    ULONG _tx_misra_time_stamp_get(VOID);
    #define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
    #endif

  5. 将内联初始化选项更改为以下内容(这也会禁用内联程序集中的宏):

    #ifdef TX_MISRA_ENABLE
    #define TX_DISABLE_INLINE
    #else
    #define TX_INLINE_INITIALIZATION
    #endif

  6. 确保禁用堆栈检查选项:#ifndef TX_MISRA_ENABLE
    #ifdef TX_ENABLE_STACK_CHECKING
    #undef TX_DISABLE_STACK_FILLING
    #endif
    #endif