为什么 MISRA-C 检查器会对 STM32 HAL 进行错误检查?

问题描述

我已经使用 stm32cubemx 启动了一个带有 HAL 库的项目,但似乎存在 HAL 和 MISRA-C 合规性问题。

我使用 Keil 进行软件开发,并且添加了 PC-Lint(MISRA-C 检查器)来检查 C 标准。当我运行 PC-lint 来检查 MISRA-C 规则时,我收到了大量由 HAL 命令引起的 MISRA-C 2012 违规规则。

注意,除了 stm32cube 生成的源文件之外,我没有输入任何源文件

例如生成文件包含以下两行:

HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)

但我因此收到这些错误

: Note 934: Taking address of near auto variable 'GPIO_InitStruct' (arg. no. 2) [MISRA 2012 Rule 1.3,required]
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)

我还收到了许多其他错误。根据 this ,HAL 符合 MISRA C 2012。有什么问题?

解决方法

大多数董事会支持包导致违反 MISRA C 规则。

这是因为,一般来说,这些 BSP 所做的事情(大部分时间)并不是好主意。有时,它们是必要的(例如,内存映射寄存器需要将整数转换为指针,尽管这可以在链接器中完成)

它们通常还包含许多特定于编译器的魔法(因此规则 1.1、规则 1.2 和指令 1.1 值得适当审查!)

因此,您需要将违规行为分为三组。

  1. 纠正需要修复的违规行为
  2. 需要偏离的必要违规
  3. 您可以接受的建议违规(并记录您的理由)

请记住:偏差是 MISRA 合规性的一个可接受的方面!任何表明您不允许出现偏差的剪贴板监视器都需要进行一些再教育。

对于第 2 组,MISRA 发布了一些偏差许可来帮助您...

免责声明:查看个人资料

PS:为了避免@Lundin 发表评论,尽管我有专业从属关系,PC-Lint 并不是分析仪的最佳选择。

-- 已编辑--

据此,HAL 符合 MISRA C 2012。

根据(现在添加的)链接

HAL 和 LL API 已投入生产,开发符合 MISRA-C®:2012 指南并使用 CodeSonar 静态分析进行检查 工具。报告可按需提供。

您需要索取这些报告,看看他们怎么说。我很想自己去问他们......

由于他们声称符合 MISRA C 2012,因此将有一份指南合规摘要(以及其他一些内容)...如果没有,则他们不合规。

,

这里有两个不同的问题:静态分析器工具和 ST 库:


规则 1.3 只是说您的程序中不应有未定义或严重未指定的行为。一个非常宽泛和模糊的规则。返回一个指向局部变量的指针来自 一个函数将违反该规则。将指向局部变量的指针传递给函数不是。 HAL_GPIO_Init 除了读取该指针外,不会对该指针执行任何操作。

这就是我们所说的“误报”,也称为工具错误。询问您的工具供应商,为什么他们的工具会给出错误的诊断消息。


然而,由于 HAL_GPIO_Init 不修改传递的指针,它应该将函数声明为:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx,const GPIO_InitTypeDef *GPIO_Init)`

由于他们没有这样做,因此违反了 MISRA-C 规则 8.13。该功能 MISRA 兼容,除非有记录的偏差。 Doxygen 对该函数实现的源代码注释(我承认是在一些随机 Github 上发现的)根本没有提到 MISRA,因此可以很安全地假设该库不符合 MISRA。

,

这不是 HAL 库问题,只是您的代码有问题(即使它是由 Cube 生成的。

这里出了什么问题?

您将引用传递给局部变量。如果代码id是单线程的或者被调用的函数在函数返回后不使用数据,一切都很好。

但是(即使您不使用多线程)许多功能将在后台运行。例如 *_IT 和 *_DMA 函数。您将引用传递给具有自动存储持续时间的缓冲区,您将遇到大问题。

所以 Lint 是正确的。您进行了具有潜在危险的操作。