1

I'm using "IAR RL78" and "RL78-R5F10BGG" microcontroller. I also have enabled MISRA C 2004 in IAR.

I wanna define one of my functions as "inline". This inline function is supposed to be used in various c file. So I have defined the function in one of my

header files and include that header file in all c files which need the function. But my problem is because of MISRA C 8.5 rule after compilation. It says:

Error[Pm123]: there shall be no definition of objects or functions in a header file (MISRA C 2004 rule 8.5)

The following is the definition of the inline function in common.h header:

static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex);

#pragma inline=forced
static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex)
{
     int16uVar |= ( (int16u)1u << (int16uBitIndex) );

     return int16uVar ;
}

What's the problem?

Is there any way to get rid of this problem?

Lundin
  • 195,001
  • 40
  • 254
  • 396
Anmk
  • 193
  • 1
  • 9
  • Q: What is int16u ? Does the u suffix mean unsigned? In that case do you want to use uint16_t from ? – Razzle Dec 15 '20 at 10:18

3 Answers3

2

MISRA-C:2004 does not cover C99, so you simply cannot use inline at all.

And because of this, the rule about function definitions in header files strikes bluntly even at inline functions. There is no way you can conform to MISRA-C:2004 with the posted code - you will have to create deviations from several required rules.


My recommendation is to upgrade to MISRA-C:2012, which has an explicit exception for this scenario (rule 5.9):

Exception
An inline function with internal linkage may be defined in more than one translation unit provided that all such definitions are made in the same header file that is included in each translation unit.

MISRA-C:2012 also requires that all inline function must declared as static (rule 8.10).

MISRA-C:2012 is a much better document in almost every way. IAR have got support for the 2012 version too and their MISRA checker should be a separate plug-in not related to the specific MCU.


Unrelated to your actual question (int16u)1u << is completely wrong and dangerous.

If you actually must have signed types (most often you don't), then you must first carry out the shift on unsigned type, then convert to signed.

This is not just needed for MISRA-C compliance, but to fix a blatant C bug that invokes undefined behavior on 8 and 16 bit MCUs, when you left shift data into the sign bit.

Correct code should be int16uVar |= (int16u)(1u << int16uBitIndex); and I believe this also sates the MISRA-C:2004 requirements about casting to the underlying type after the operation.


Also note that creating your own "garage standard" integer types is frowned upon in general - since you are using C99 you should be using stdint.h and nothing else. This is also the MISRA-C:2012 recommendation.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • MISRA-C is actually a standard of the automotive industry, and with AUTOSAR more and more accepted, the types like uint8 / sint8, uint8 / uint16 ... are actually defined in Platform_Types.h (included over Std_Types.h). which should actually be used instead of compiler stdint.h. And second, its not a C-Bug but a definition of the C-language and its abstract machine how bitwise ops are working (incl impl-defined and undefined behaviour) and its not just 8/16bit MCUs but also 32bit MCUs. – kesselhaus May 22 '20 at 10:55
  • 1
    @kesselhaus No that's not correct. ISO C is more canon than MISRA-C, which is more canon than AUTOSAR. Furthermore, it's been ages since MISRA-C was just for automotive. Everyone uses it nowadays, even outside embedded systems. Regarding left-shift, it's only dangerous and undefined if you either shift negative numbers, or if you shift data into the sign bit of a signed number. Meaning that on a signed 16 variable, left-shifting 15 bits or more is always a bug. Casting from an unsigned to signed type, as I thought this was, is highly questionable. Code invoking undefined behavior = bug. – Lundin May 25 '20 at 14:19
  • Especially in Automotive, almost any OEM is asking now for AUTOSAR, and at least Tier1 suppliers going the route if they have to support multiple OEMs. Here, stdint.h is and should NOT be directly used at all. And btw, 32bit MCUs have the same problem with sint32. And signed left shift will is defined as "undefined behaviour" and signed right-shift "implementation defined behaviour". And yes, MISRA-C might be used also outside automotive by now, (I just guessed from MISRA-C on auromotive env. here) – kesselhaus May 27 '20 at 02:55
0

Thank you Lundin for your helpful reply. About the second part of your reply, I should say that in our coding style we use int16u for unsigned int types. that is

typedef unsigned int int16u

So I'm shifting the unsigned int not signed int. there is a typing error in my question and that is, I have written

int16uVar |= ( (int16u)1u << (int16uBitIndex) );

but the correct line in my code is

int16uVar |= ( (int16u)1 << (int16uBitIndex) );

I do apologize.

Anmk
  • 193
  • 1
  • 9
  • 1
    Yikes, you really shouldn't name your types like that. `int16_t` vs `int16u`, easy to mix up. Regardless, the cast should be after the shift for MISRA-C:2004 underlying type. – Lundin May 20 '20 at 13:28
0

In simple terms, inline is not part of C90 (as covered by MISRA C:2004)

However, there is a workaround, if you adopt MISRA Compliance... this introduces the concept of Deviation Permits, and the MISRA team conveniently provide you with such a Permit for using inline (Permit/MISRA/C:2004/1.1.C.1)

Of course, most compilers simply ignore the inline qualifier anyway...

Declaration of Interest: See profile!

Andrew
  • 2,046
  • 1
  • 24
  • 37