如何解决MISRA C:2012规则11.6?

时间:2019-01-10 02:52:54

标签: c embedded misra

我正在使用Microchip的示例nvmem.c文件功能将数据写入PIC32微控制器的特定存储器地址。当我尝试使用它时,显示以下MISRA错误:我只是在出现错误的地方发布了示例代码。我的整个代码已编译并且可以正常工作。

  

1]在NVMemWriteWord((void )APP_FLASH_MARK_ADDRESS,(UINT)_usermark);

处从“ unsigned int”显式转换为“ void ” [MISRA 2012规则11.6,必需]

如何解决此错误?

nvmem.c
uint8_t NVMemWriteWord(void* address, uint32_t data)
{
    uint8_t res;
    NVMADDR = KVA_TO_PA((uint32_t)address); //destination address to write
    NVMDATA = data;
    res = NVMemOperation(NVMOP_WORD_PGM);
}

test.c
#define ADDRESS 0x9D007FF0U;
NVMemWriteWord((void*)ADDRESS,(uint32_t)_usermark);

3 个答案:

答案 0 :(得分:2)

使用

uint8_t NVMemWriteWord(unsigned int  address, uint32_t data)
{
    uint8_t res;
    NVMADDR = KVA_TO_PA(address);
    NVMDATA = data;
    res = NVMemOperation(NVMOP_WORD_PGM);
}

#define  ADDRESS  0x9D007FF0U

NVMemWriteWord(ADDRESS,(uint32_t)_usermark);

相反。从功能上讲,它与示例完全等效,只是避免了将void指针强制转换为无符号整数地址。

答案 1 :(得分:1)

建议:

#define ADDRESS (volatile uint32_t*)0x9D007FF0U
NVMemWriteWord( ADDRESS, _usermark) ;

从不强制转换为void*-void*的目的是您可以安全地为其分配任何其他指针类型,而无需显式强制转换。 _usermark的强制转换可能有必要,也可能没有必要,但应避免不必要的显式强制转换-它们可以抑制重要的编译器警告。您应该按照以下优先顺序进行类型转换:

  • 类型协议-完全相同的类型。
  • 类型兼容性-较小的类型到较大的类型,相同的签名。
  • 类型区分大小写-不得已(例如,从大到小的类型,符号不匹配,指针到/从指针到整数)。

在这种情况下,由于NVMemWriteWord仅将address强制转换为整数,因此使用void*可能不合适。如果在其他情况下实际上正在使用指针,则它可能是有效的。

答案 2 :(得分:0)

关于指针转换的整个MISRA-C:2012第12章都相当挑剔。没错,因为这是非常危险的领域。

11.6是一个健全的规则,禁止从整数到void*的转换。基本原理是阻止对齐错误。无论如何,没有太多理由要进行此类转换。

值得注意的是,还有两个严格但建议性的规则11.4禁止从整数到指针的转换,而规则11.5则完全禁止使用void*。不可能进行与硬件相关的编程并遵循11.4,因此必须忽略该规则。但是您没有理由使用void*

在此特定类型的转换中,您可以通过使用uint32_t并完全避免使用指针来摆脱困境。

在寄存器访问的一般情况下,您必须使用volatile限定指针(volatile uint32_t*)ADDRESS进行转换,假设MCU使用32位寄存器。