面对与MISRA C 2012规则11.4违反有关的问题。使用PC-Lint Plus进行规则检查。Keil uVision V5.38.0.0
错误代码:
conversion between object pointer type 'GPIO_Type *' and integer type 'unsigned int' [MISRA 2012 Rule 11.4, advisory]```
uint *L_uc_byte = (uint *)&GPIO->PIN[0];
字符串
以下是与GPIO相关的详细信息
#define __IO volatile /*!< Defines 'read / write' permissions */
/** Peripheral GPIO base address */
#define GPIO_BASE (0x4008C000u)
/** Peripheral GPIO base pointer */
#define GPIO ((GPIO_Type *)GPIO_BASE)
/** GPIO - Register Layout Typedef */
typedef struct {
__IO uint8_t B[6][32]; /**< Byte pin registers for all port 0 and 1 GPIO pins, array offset: 0x0, array step: index*0x20, index2*0x1 */
uint8_t RESERVED_0[3904];
__IO uint32_t W[6][32]; /**< Word pin registers for all port 0 and 1 GPIO pins, array offset: 0x1000, array step: index*0x80, index2*0x4 */
uint8_t RESERVED_1[3328];
__IO uint32_t DIR[6]; /**< Direction registers, array offset: 0x2000, array step: 0x4 */
uint8_t RESERVED_2[104];
__IO uint32_t MASK[6]; /**< Mask register, array offset: 0x2080, array step: 0x4 */
uint8_t RESERVED_3[104];
__IO uint32_t PIN[6]; /**< Port pin register, array offset: 0x2100, array step: 0x4 */
uint8_t RESERVED_4[104];
__IO uint32_t MPIN[6]; /**< Masked port register, array offset: 0x2180, array step: 0x4 */
uint8_t RESERVED_5[104];
__IO uint32_t SET[6]; /**< Write: Set register for port Read: output bits for port, array offset: 0x2200, array step: 0x4 */
uint8_t RESERVED_6[104];
__O uint32_t CLR[6]; /**< Clear port, array offset: 0x2280, array step: 0x4 */
uint8_t RESERVED_7[104];
__O uint32_t NOT[6]; /**< Toggle port, array offset: 0x2300, array step: 0x4 */
uint8_t RESERVED_8[104];
__O uint32_t DIRSET[6]; /**< Set pin direction bits for port, array offset: 0x2380, array step: 0x4 */
uint8_t RESERVED_9[104];
__O uint32_t DIRCLR[6]; /**< Clear pin direction bits for port, array offset: 0x2400, array step: 0x4 */
uint8_t RESERVED_10[104];
__O uint32_t DIRNOT[6]; /**< Toggle pin direction bits for port, array offset: 0x2480, array step: 0x4 */
} GPIO_Type;
型
我试过很多方法
1.
conversion between object pointer type 'GPIO_Type *' and integer type 'unsigned int' [MISRA 2012 Rule 11.4, advisory]
uint data = ( ( GPIO->PIN[0] >> 17U ) & 0x03U );
型
1.
conversion between object pointer type 'uint *' (aka 'unsigned int *') and integer type 'volatile uint32_t' (aka 'volatile unsigned int') [MISRA 2012 Rule 11.4, advisory]
volatile uint L_uc_byte = *( uint * )(GPIO->PIN[0]);
型
1.
conversion between object pointer type 'GPIO_Type *' and integer type 'unsigned int' [MISRA 2012 Rule 11.4, advisory]
uint L_uc_byte = GPIO->PIN[0];
型
1.使用地址文字作为指针
conversion between object pointer type 'uint *' (aka 'unsigned int *') and integer type 'unsigned int' [MISRA 2012 Rule 11.4, advisory]
uint L_uc_byte = *( uint * )( 0x40002000U + 0x2100U);
需要解决方案来解决此规则冲突。
3条答案
按热度按时间yhuiod9q1#
uint
类型--不要发明奇怪的非标准的、非自文档化的整数类型。使用标准Cuint32_t
。volatile
限定表达式(例如阅读/写寄存器)与其他操作数或子表达式(以及另一个MISRA违规)混合。这对性能目的和清晰度不利,并且额外的副作用可能会给予不可预测的结果。尝试使寄存器访问表达式只执行写或读操作,而不执行其他操作。volatile
限定的uint*
是永远不正确的。特别是,它几乎肯定永远不是正确的路线去的情况下,你得到警告。x >> 17 & 42
这样的“魔术数字”,因为它们使代码不可读,并迫使读者坐在那里,鼻子一直埋在MCU手册的寄存器描述中。使用有意义的名字。如果您使用的是MCU供应商提供的寄存器Map,则它通常带有可供使用的命名常量。详情如下:How to access a hardware register from firmware?
此外,MISRA-C有一些过于迂腐的建议规则,并不真正适用于嵌入式系统。其中一条规则禁止整数和指针之间的转换,但是没有办法在不执行这种类型转换的情况下定义寄存器Map,因此必须忽略该规则。
MISRA的关键是理解 * 为什么 * 他们首先制定了规则。这种情况下的主要问题是对齐,像
uint32_t* data = (uint32_t*)0x0003;
这样的东西会导致指针不对齐。如果你明白为什么这是一个严重的错误,那么你就明白为什么MISRA制定了这个规则。如果您不打算提供任何类似的自制地址,则可以安全地忽略该规则。标准的做法是,跳过咨询规则不需要正式的偏离。尽管理想情况下,基于MISRA的编码标准应该列出所有可以忽略的建议规则,然后在静态分析器/MISRA检查器中相应地禁用它们。
结论:
uint data = ( ( GPIO->PIN[0] >> 17U ) & 0x03U );
更改为uint32_t data
并将常量命名为有意义的名称。理想情况下,为了符合MISRA,您还应该将其拆分为几个表达式,这有点过分,但应该100%符合MISRA:字符串
如果忽略整数到指针的建议规则,我们应该这样做:
型
kyxcudwk2#
如果您计划在多个位置使用GPIO,则至少可以在单个位置发生MISRA违规。
创建一个如下的peripherl.h文件:
字符串
创建如下所示的peripheral.c文件:
型
现在,您可以在代码中使用GPIO指针,而不会发生这种冲突;
main.c
型
h6my8fg23#
MISRA承认,某些指南可能会对合法用例造成问题......这就是为什么我们创建了偏差流程,如MISRA Compliance中所述。
同样,对于咨询指南(如R.11.4),这些可以 * 不适用 *。
R.11.4甚至包括(在基本原理中)一个声明,大意是在寻址内存Map寄存器 * 时可能需要违反此规则 *。
因此,正确的方法(除了Lundin的优秀建议之外)不是忽略R.11.4,而是(有正当理由)不适用它
--联系方式见个人资料