How to make (1 << 9) pass MISRA? [duplicate]

橙三吉。 提交于 2019-12-08 17:37:56

问题


We are using Parasoft Static Analysis with MISRA C 2004 checker turned on.

The software is an embedded system. We like to describe constants as follows:

[1]    #define MOTOR_ON (1 << 9)  

This would show that the 9th bit in the register should be a 1 to turn on the motor.

The expression is failing MISRA, so we changed it:

[2]    #define MOTOR_ON (1U << 9U)

The changes convert to unsigned integer constants because shifting is best done with unsigned integers.

The expression in statement 2, is still failing because of the right hand operator (9U) needs checking. According to MISRA, if the right hand operator is larger than the bit width of the underlying type of the left hand operator, there is a problem.

The base of the problem is that 1U has an underlying type of unsigned char or 8-bits.
The register we are writing to is 16-bits, so theoretically there is not an issue.

How can I change the expression in [2] so that it passes MISRA C 2004, preferring not to use casts?

I'm using IAR Embedded Workbench with an ARM7TDMI processor in 8/32 bit mode.

Edit 1: Example code.

void turn_on_motor(void);
#define MOTOR_ON (1U << 9U)
void turn_on_motor(void)
{
    uint16_t * const p_motor_control = (uint16_t *)(0x01234567U);
    *p_motor_control = MOTOR_ON;
}

Error text: Constant used as the right-hand operand of a shift operator shall be limited.

From the MISRA Rule documentation provided by Parasoft:

Rule reports a violation if:

- the right-hand operand is a constant with negative value or with value that
  exceeds the length (in bits) of the left-hand operand

- the right-hand operand is not a constant and is not checked by specific
  pattern

回答1:


You could also simply circumvent the shifting issue by using

 #define MOTOR_ON ((uint16_t)512U)   /* 1 << 9 = 2^9 */



回答2:


My advice is to define a macro that hides the ugly casting, but then go ahead and do the ugly casting to make MISRA happy.

Something like:

#define LSHIFT(x, n) \
    (((unsigned int)(x)) << ((unsigned int)(n)))

Then in your actual code:

#define MOTOR_ON LSHIFT(1, 9)

EDIT: In a comment below, @Lundin says that MISRA will complain about function-like macros. I've never used MISRA so I didn't know that.

A quick Google search finds that MISRA has special comments you can add to your code to disable warnings. This suggests two possibilities:

  • In your header file where you define LSHIFT() and RSHIFT() and any other bit-manipulating macros, wrap the macro definitions in the MISRA warning disable comments.

  • In your source file where you want to put the bit-shifting, add MISRA warning disable comments and just put your code as you had it before.

http://www.gimpel.com/Discussion.cfm?ThreadMode=Prev&ThreadID=2261

If I'm understanding correctly, MISRA has global enable/disable but does not have disable followed by "put it back the way it was". So, the comments to disable and then enable will always globally enable the check, so ideally these magic comments shouldn't be in a header file.

So I guess my suggestion now is to put your original bit shifting code int a .C source file, and put the magic comments to disable/enable the MISRA warnings around the bit shifting code.




回答3:


The value of expression is being assigned to an object with a narrower type. “1U << 9U” results in only preserving the low-order bits.

“Making MISRA happy” with ugly casting won’t change this fact, though a poor tool might be gamed, it shouldn’t.

The straightforward solution is to use an explicit cast :

#define MOTOR_ON ((uint16_t)0x200) /* 9th bit on turns on motor */

but if you believe the “shift is better for readability” then simply turn off the rule for this case and document the reasoning. The deviation process is perfectly fine (and encouraged) in MISRA compliant development, if fact complete conformance is impossible. You have to have a deviation management process to be fully compliant. Evidence of awareness is the goal, not evidence of conformance.

BTW, @Thomas, you are right, this is not an exact duplicate of MISRA C:2004, error with bit shifting which you also wrote. Though it is a Rule 10.3 violation, the concepts of “underlying type” described does little to help understand the intent of this warning for this specific question. My suggestion to all is taking a look at the description for Rule 10.3 in the latest version of MISRA-C:2012 (found here: http://misra.org.uk ) which makes the concepts and intent much more clear for engineers and tool makers.



来源:https://stackoverflow.com/questions/21537030/how-to-make-1-9-pass-misra

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!