roc*_*23A 1 c embedded misra keil pc-lint
面临与违反 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];
Run Code Online (Sandbox Code Playgroud)
以下是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;
Run Code Online (Sandbox Code Playgroud)
我尝试过多种方法
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 );
Run Code Online (Sandbox Code Playgroud)
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]);
Run Code Online (Sandbox Code Playgroud)
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];
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
需要解决方案来解决此违反规则的问题。
您需要uint从代码库中消除这种奇怪的类型 - 不要发明奇怪的非标准、非自记录的整数类型。使用标准 C uint32_t。
请注意,最好避免将volatile限定表达式(例如读取/写入寄存器)与其他操作数或子表达式混合(以及另一个 MISRA 违规)。这不利于性能目的和清晰度,而且额外的副作用可能会产生不可预测的结果。尝试使寄存器访问表达式仅执行写入或读取操作,而不执行其他操作。
除非您对 C 有深入的了解,否则切勿执行指针转换。将整数转换为不合格的 auint*永远volatile不会正确。特别是,如果您收到警告,它几乎肯定不是正确的路线。
不应使用诸如此类的“魔术数字” x >> 17 & 42,因为它们会使代码难以阅读,并迫使读者不断地埋头于 MCU 手册的寄存器描述中。相反,使用有意义的名称。如果您使用 MCU 供应商提供的寄存器映射,它通常附带您可以使用的命名常量。
详细信息此处:如何从固件访问硬件寄存器?
此外,MISRA-C 有一些过于迂腐的建议规则,并不真正适用于嵌入式系统。其中一条规则禁止整数和指针之间的转换,但如果不执行此类转换,就无法定义寄存器映射,因此必须忽略该规则。
MISRA 的关键是首先了解他们制定该规则的原因。这种情况下的主要问题是对齐,这uint32_t* data = (uint32_t*)0x0003;会导致指针未对齐。如果您了解为什么这是一个严重的错误,那么您就会了解 MISRA 制定该规则的原因。鉴于您不会提供任何类似的自制地址,因此您可以安全地忽略该规则。
标准做法是,您无需正式偏离即可跳过咨询规则。尽管理想情况下,基于 MISRA 的编码标准应列出所有可以忽略的建议规则,然后应在静态分析器/MISRA 检查器中相应地禁用它们。
结论:
uint data = ( ( GPIO->PIN[0] >> 17U ) & 0x03U );uint32_t data将常量更改为有意义的名称。理想情况下,为了符合 MISRA 要求,您还应该将其分成几个表达式,这有点过分热心,但应该 100% MISRA 兼容:
uint32_t data = GPIO->PIN[0]; // volatile expression as a stand-alone read/write
// just making up some names here, refer to the MCU manual for proper names:
data = (data >> GPIO_POS ) & GPIO_MASK;
Run Code Online (Sandbox Code Playgroud)
如果我们应该忽略整数到指针的咨询规则:
#define SOME_REGISTER (*(volatile uint32_t*)(0x40002000U + 0x2100U))
...
uint32_t L_uc_byte = SOME_REGISTER;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
828 次 |
| 最近记录: |