Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 747
Thomas Matthews Avatar asked Feb 03 '14 20:02

Thomas Matthews


2 Answers

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.

like image 196
steveha Avatar answered Sep 29 '22 07:09

steveha


You could also simply circumvent the shifting issue by using

 #define MOTOR_ON ((uint16_t)512U)   /* 1 << 9 = 2^9 */
like image 36
Jens Avatar answered Sep 29 '22 07:09

Jens