简体   繁体   English

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

[英]How to resolve MISRA C:2012 Rule 11.6?

I am utilizing Microchip sample nvmem.c file function to write data into particular memory address of PIC32 Microcontroller. 我正在利用Microchip的样本nvmem.c文件功能将数据写入PIC32单片机的特定存储器地址。 When I am trying to use it showing following MISRA error: I just posted sample code where I got an error. 当我尝试使用它时,显示以下MISRA错误:我只是在出现错误的地方发布了示例代码。 My whole code is compiled and working fine. 我的整个代码已编译并且可以正常工作。

1] explicit cast from 'unsigned int' to 'void ' [MISRA 2012 Rule 11.6, required] at NVMemWriteWord((void )APP_FLASH_MARK_ADDRESS,(UINT)_usermark); 1] 在NVMemWriteWord((void )APP_FLASH_MARK_ADDRESS,(UINT)_usermark)中从“ unsigned int”显式转换为“ void ” [MISRA 2012 Rule 11.6,必填]

How can I resolve this error? 如何解决此错误?

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);

Use 采用

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

and

#define  ADDRESS  0x9D007FF0U

NVMemWriteWord(ADDRESS,(uint32_t)_usermark);

instead. 代替。 Functionally it is exactly equivalent to the example, it just avoids the cast from a void pointer to an unsigned integer address. 从功能上讲,它与示例完全等效,只是避免了将void指针强制转换为无符号整数地址。

Suggest: 建议:

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

Never cast to void* - the purpose of void* is that you can assign any other pointer type to it safely and without explicit cast. 决不强制转换为void* -目的void*是,你可以放心地和没有明确的投任何其他指针类型分配给它。 The cast of _usermark may or may not be necessary, but unnecessary explicit casts should be avoided - they can suppress important compiler warnings. _usermark强制转换可能是必需的,也可以不是必需的,但应避免不必要的显式强制转换-它们可以抑制重要的编译器警告。 You should approach type conversions in the following order of preference: 您应该按照以下优先顺序进行类型转换:

  • Type agreement - exactly same types. 类型协议-完全相同的类型。
  • Type compatibility - smaller type to larger type, same signedness. 类型兼容性-较小的类型到较大的类型,相同的符号。
  • Type case - last resort (eg larger to smaller type, signedness mismatch, integer to/from pointer). 类型大小写-不得已(例如,较大到较小的类型,符号不匹配,指针往返整数)。

In this instance since NVMemWriteWord simply casts address to an integer, then the use of void* may not be appropriate. 在这种情况下,由于NVMemWriteWord只是将address转换为整数,因此使用void*可能不合适。 If in other contexts you are actually using a pointer, then it may be valid. 如果在其他情况下实际上正在使用指针,则它可能是有效的。

The whole of MISRA-C:2012 chapter 12 regarding pointer conversions is quite picky. MISRA-C:2012第12章中有关指针转换的整个内容都很挑剔。 And rightly so, since this is very dangerous territory. 没错,因为这是非常危险的领域。

11.6 is a sound rule that bans conversions from integers to void* . 11.6是一个健全的规则,禁止从整数到void*转换。 The rationale is to block alignment bugs. 基本原理是阻止对齐错误。 There aren't many reasons why you would want to do such conversions anyway. 无论如何,没有太多理由要进行此类转换。

Notably, there's also two rigid but advisory rules 11.4 which bans conversions from integers to pointers, and 11.5 which pretty much bans the use of void* entirely. 值得注意的是,还有两个严格但建议性的规则11.4禁止从整数到指针的转换,而规则11.5则完全禁止使用void* It isn't possible to do hardware-related programming and follow 11.4, so that rule has to be ignored. 不可能进行与硬件相关的编程并遵循11.4,因此必须忽略该规则。 But you have little reason to use void* . 但是您没有理由使用void*

In this specific cast you can get away by using uint32_t and avoiding pointers entirely. 在此特定的转换中,您可以通过使用uint32_t并完全避免使用指针来摆脱uint32_t

In the general case of register access, you must do a conversion with volatile -qualified pointers: (volatile uint32_t*)ADDRESS , assuming that the MCU uses 32 bit registers. 在寄存器访问的一般情况下,您必须使用volatile限定的指针进行转换: (volatile uint32_t*)ADDRESS ,假设MCU使用32位寄存器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM