问题描述
我在C程序中将CMSIS API用于ARM Cortex-M CPU。
CMSIS将NVIC_DisableIRQ
函数定义为
__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn);
IRQn_Type是typedef enum
,例如
typedef enum IRQn
{
NonMaskableInt_IRQn = -14,/* 2 Non Maskable Interrupt */
HardFault_IRQn = -13,/* 3 HardFault Interrupt */
.....
Interrupt0_IRQn = 0,Interrupt1_IRQn = 1,Interrupt2_IRQn = 2,} IRQn_Type;
因此,鉴于我想称呼NVIC_DisableIRQ
为
NVIC_DisableIRQ( (IRQn_Type )(SCB->ICSR -16);
这使MISRA检查失败
注释9034:无法将'unsigned32'分配给其他基本类型 “枚举(IRQn)” [MISRA 2012规则10.3,必填]
我理解MISRA为什么会抱怨,但这是一个切实可行的解决方案? 我发现是要创建巨大的switch / case,是否有其他解决方案/黑客可用?
解决方法
假设SCB->ICSR -16
结果为uint32_t
,则不能将其分配给enum
变量(10.3),也不能将其强制转换为{{1 }}(10.5)。这是因为枚举具有实现定义的大小和签名。
我想可能有各种肮脏的技巧来躲避MISRA,但这违背了这些规则的合理依据,这些原则归结为:不要在代码中使用带符号的操作数,以使它在各种细微的地方变得混乱。严厉的方法。例如更改默认的编译器枚举类型会导致所有中断更改行为-这是不好-可能会很危险。
问题的根源是enum
类型和需要enum
的CMSIS函数__NVIC_DisableIRQ
。如果用不同的方式编写该代码,则可以使用无符号类型。奇怪的是,草率的,不符合MISRA规范的库仍在2020年推出。
我建议您删除该函数并编写一个自定义函数。这些功能大多数只是简单的单行汇编程序指令的包装器,还是无论如何都要进行寄存器写操作,因此,如果您可以访问该函数的实现,则可能不会花费很多精力。
请注意,MISRA-C(10.5)允许从枚举到无符号的转换,因此,如果您基于enum
创建API,则仍然可以通过强制转换来传递枚举值。